├── .gitattributes ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── contributing.md └── workflows │ ├── msbuild.yml │ ├── pr-comment.yml │ └── release.yml ├── .gitignore ├── .idea └── .idea.TestFlight │ └── .idea │ └── .gitignore ├── CHANGELOG.md ├── CachedEngineState.cs ├── EngineRunData.cs ├── ExampleConfig.cfg ├── Failure Bases ├── TestFlightFailureBase_Avionics.cs ├── TestFlightFailureBase_Docking.cs ├── TestFlightFailureBase_FARCtrlSrf.cs ├── TestFlightFailureBase_Generic.cs ├── TestFlightFailureBase_Gimbal.cs ├── TestFlightFailureBase_Light.cs ├── TestFlightFailureBase_ReactionWheel.cs ├── TestFlightFailureBase_Science.cs ├── TestFlightFailureBase_Solar.cs └── TestFlightFailureBase_Wheel.cs ├── Failure Modules ├── TestFlightFailure_AblatorCover.cs ├── TestFlightFailure_Animation.cs ├── TestFlightFailure_AvionicsAxis.cs ├── TestFlightFailure_AvionicsClamp.cs ├── TestFlightFailure_AvionicsDeadzone.cs ├── TestFlightFailure_AvionicsGlitch.cs ├── TestFlightFailure_AvionicsInvert.cs ├── TestFlightFailure_AvionicsPartial.cs ├── TestFlightFailure_AvionicsThrustJam.cs ├── TestFlightFailure_AvionicsTotal.cs ├── TestFlightFailure_DockingClamp.cs ├── TestFlightFailure_DockingFeed.cs ├── TestFlightFailure_EngineCoolant.cs ├── TestFlightFailure_FARCtrlSrfGlitch.cs ├── TestFlightFailure_FARCtrlSrfMech.cs ├── TestFlightFailure_GimbalCenter.cs ├── TestFlightFailure_GimbalSpeed.cs ├── TestFlightFailure_LightBroken.cs ├── TestFlightFailure_LightFlicker.cs ├── TestFlightFailure_ReactionBroken.cs ├── TestFlightFailure_ReactionTorque.cs ├── TestFlightFailure_RemoteBroken.cs ├── TestFlightFailure_RemotePassiveBroken.cs ├── TestFlightFailure_ResourcePump.cs ├── TestFlightFailure_ScienceBroken.cs ├── TestFlightFailure_ScienceCollect.cs ├── TestFlightFailure_ScienceXmit.cs ├── TestFlightFailure_SolarMech.cs ├── TestFlightFailure_SolarTracking.cs ├── TestFlightFailure_WheelBrake.cs ├── TestFlightFailure_WheelMotor.cs └── TestFlightFailure_WheelSteer.cs ├── Flight Recorders ├── FlightDataRecorder_DockingPort.cs ├── FlightDataRecorder_FARCtrlSrf.cs ├── FlightDataRecorder_HeatShield.cs ├── FlightDataRecorder_Intake.cs ├── FlightDataRecorder_Lights.cs ├── FlightDataRecorder_RCS.cs ├── FlightDataRecorder_RT.cs ├── FlightDataRecorder_ReactionWheel.cs ├── FlightDataRecorder_Science.cs ├── FlightDataRecorder_Solar.cs └── FlightDataRecorder_Wheels.cs ├── FlightDataRecorder.cs ├── FlightDataRecorder_Engine.cs ├── FlightDataRecorder_Resources.cs ├── GameData └── TestFlight │ ├── Config │ └── ignore.txt │ ├── Resources │ ├── AppLauncherIcon.png │ ├── ChevronDown.png │ ├── ChevronLeft.png │ ├── ChevronRight.png │ ├── ChevronUp.png │ └── Textures │ │ ├── img_PanelBack.png │ │ ├── img_PanelBack_Trans.png │ │ ├── img_PanelSolarizedDark.png │ │ ├── img_PartWindowHead.png │ │ ├── img_SeparatorHorizontal.png │ │ ├── img_SeparatorVertical.png │ │ ├── tex_Box.png │ │ └── tex_BoxUnity.png │ └── TestFlight.version ├── KSP_VERSION ├── Properties └── AssemblyInfo.cs ├── RELEASE_NOTES_RAW.txt ├── Reliability Modules ├── TestFlightReliability_DynamicPressure.cs ├── TestFlightReliability_InternalTemperature.cs └── TestFlightReliability_SkinTemperature.cs ├── TestFlight.csproj ├── TestFlight.netkan ├── TestFlight.sln ├── TestFlight.userprefs ├── TestFlightAPI ├── TestFlightAPI.sln ├── TestFlightAPI.userprefs └── TestFlightAPI │ ├── EngineModuleWrapper.cs │ ├── FlightDataRecorder.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── TestFlightAPI.cs │ ├── TestFlightAPI.csproj │ ├── TestFlightAPI_WIN.csproj │ ├── TestFlightFailure.cs │ ├── TestFlightInterop.cs │ ├── TestFlightPartData.cs │ ├── TestFlightReliability.cs │ └── custom.targets ├── TestFlightConfigStock.netkan ├── TestFlightContracts ├── MyClass.cs ├── Properties │ └── AssemblyInfo.cs ├── TestFlightContractConfigurator.cs ├── TestFlightContracts.csproj └── custom.targets ├── TestFlightCore ├── TestFlightCore.sln ├── TestFlightCore.userprefs └── TestFlightCore │ ├── BodySettings.cs │ ├── FlightDataConfig (copy).cs │ ├── Framework │ ├── ConfigNodeStorage.cs │ ├── ExtensionsUnity.cs │ ├── MonoBehaviourExtended.cs │ ├── MonoBehaviourWindow.cs │ ├── PartModuleExtended.cs │ └── SkinsLibrary.cs │ ├── FrameworkExt │ ├── Extensions.cs │ └── MonoBehaviourWindowPlus.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Resources.cs │ ├── StylesAndSkins.cs │ ├── TestFlight.cs │ ├── TestFlightCore.cs │ ├── TestFlightCore.csproj │ ├── TestFlightCore_WIN.csproj │ ├── TestFlightEditor.cs │ ├── TestFlightHUD.cs │ ├── TestFlightInterface.cs │ ├── TestFlightKSC.cs │ ├── TestFlightRnD.cs │ ├── TestFlightRnDScenario.cs │ ├── TestFlightWindow.cs │ ├── UserInterface.cs │ ├── UserSettings.cs │ ├── Utilities │ └── ConfigNodeExtensions.cs │ └── custom.targets ├── TestFlightFailure_Engine.cs ├── TestFlightFailure_EnginePerformanceLoss.cs ├── TestFlightFailure_Explode.cs ├── TestFlightFailure_IgnitionFail.cs ├── TestFlightFailure_LockGimbal.cs ├── TestFlightFailure_ReducedMaxThrust.cs ├── TestFlightFailure_ResourceLeak.cs ├── TestFlightFailure_ShutdownEngine.cs ├── TestFlightMain.sublime-project ├── TestFlightMain.sublime-workspace ├── TestFlightRF ├── Properties │ └── AssemblyInfo.cs ├── TestFlightRF.csproj ├── TestFlightRF.csproj.DotSettings ├── TestFlightRealFuels.cs └── custom.targets ├── TestFlightReliability.cs ├── TestFlightReliability_EngineCycle.cs ├── TestFlightReliability_TestFail.cs ├── TestFlightSettings.cs ├── TestFlight_WIN.csproj ├── TestFlight_WIN.sln ├── buildChangelog.py ├── buildServer.py ├── configs ├── Examples.txt ├── Stock │ ├── Squad_Engines.json │ ├── Squad_Tanks.json │ ├── Squad_Tanks.yaml │ └── Stock_Engines.yaml ├── compileConfigs.py └── compileYamlConfigs.py ├── custom.targets ├── failureProbabilityPlot.py ├── makeMeta.py ├── makefile ├── readme.md ├── release_checklist.md └── requirements.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Make sure you have read and understood the contributing guidelines! 2 | ------------------------------------------------------------------- 3 | 4 | Pull Requests that don't follow the guidelines will be rejected. If you need help or are confused just ask, and we will be glad to help. 5 | 6 | - [ ] PR being applied to the correct **Feature Branch** or **dev** 7 | - [ ] PR is **not** being sent to **master** 8 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | Contributing Information 2 | ======================== 3 | 4 | To better coordinate multiple developers as well as community additions, the TestFlight project now uses the [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) style workflow. You can read more nerdy details about this [here](http://nvie.com/posts/a-successful-git-branching-model/). 5 | 6 | The short of it is that we use multiple branches to better manage the code coming in. All contributions to TestFlight, including those by core team members, need to follow these rules, the most important of which is... 7 | 8 | Don't ever commit anything to Master 9 | ------------------------------------ 10 | No code change or pull request should ever be directly to master. Any PR opened against master will be rejected. Full stop. Any code directly commited to master outside of the normal process of merging changes in for release will be frowned upon and most likely reverted. 11 | 12 | At any given moment in time the master branch is expected to be ready for release upon a moment's notice. 13 | 14 | Pull Requests and normal development commits either go to the dev branch or to a feature branch 15 | ----------------------------------------------------------------------------------------------- 16 | In general you shoud have a branch specifically for any feature you are adding. This branch should be branched off of **dev** and will be merged back into dev once complete. If you are making a small quick fix, then it is ok to commit to, or make a PR against, the dev branch directly. 17 | 18 | When in doubt, ASK 19 | ------------------- 20 | Seriously I understand this can be confusing, especially if you don't know Git very well. Don't be afraid to ask if you are unsure. Preferabbly before you start your work as it is easier to start on the right foot than it is to try and change after the fact. 21 | -------------------------------------------------------------------------------- /.github/workflows/msbuild.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: build 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: [ master, dev ] 10 | pull_request: 11 | branches: [ master, dev ] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | # Steps represent a sequence of tasks that will be executed as part of the job 24 | steps: 25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 26 | - name: Checkout 27 | uses: actions/checkout@v2 28 | with: 29 | fetch-depth: 100 30 | 31 | - name: Download required assemblies 32 | id: download-assemblies 33 | shell: bash 34 | env: 35 | KSP_ZIP_PASSWORD: ${{ secrets.KSP_ZIP_PASSWORD }} 36 | run: | 37 | curl https://ksp-ro.s3-us-west-2.amazonaws.com/KSPAssemblies-1.12.zip --output /tmp/bins.zip 38 | KSP_DLL_PATH="/opt/ksp/assembly" 39 | echo "::set-output name=ksp-dll-path::${KSP_DLL_PATH}" 40 | mkdir -p "${KSP_DLL_PATH}" 41 | unzip -P "${KSP_ZIP_PASSWORD}" '/tmp/bins.zip' -d "${KSP_DLL_PATH}" 42 | rm '/tmp/bins.zip' 43 | 44 | - name: Build mod solution 45 | run: | 46 | rm -f ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/*.dll 47 | mkdir -p "${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/" 48 | msbuild /p:Configuration=Release /p:ReferencePath="${{ steps.download-assemblies.outputs.ksp-dll-path }}" TestFlight.sln 49 | cp -v ${GITHUB_WORKSPACE}/bin/Release/TestFlight.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlight.dll 50 | cp -v ${GITHUB_WORKSPACE}/TestFlightAPI/TestFlightAPI/bin/Release/TestFlightAPI.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlightAPI.dll 51 | cp -v ${GITHUB_WORKSPACE}/TestFlightCore/TestFlightCore/bin/Release/TestFlightCore.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlightCore.dll 52 | cp -v ${GITHUB_WORKSPACE}/TestFlightContracts/bin/Release/TestFlightContracts.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlightContracts.dll 53 | 54 | - name: Remove excess DLLs 55 | uses: KSP-RO/BuildTools/remove-excess-dlls@master 56 | with: 57 | path: ${GITHUB_WORKSPACE}/GameData/ 58 | 59 | - name: Setup python 60 | uses: actions/setup-python@v2 61 | 62 | - name: Build metadata 63 | shell: bash 64 | run: | 65 | python ${GITHUB_WORKSPACE}/makeMeta.py 2.0.0.0 66 | 67 | - name: Assemble release 68 | id: assemble-release 69 | run: | 70 | RELEASE_DIR="${RUNNER_TEMP}/release" 71 | echo "Release dir: ${RELEASE_DIR}" 72 | mkdir -v "${RELEASE_DIR}" 73 | echo "::set-output name=release-dir::${RELEASE_DIR}" 74 | cp -v -R "${GITHUB_WORKSPACE}/GameData" "${RELEASE_DIR}" 75 | 76 | - name: Upload artifacts 77 | uses: actions/upload-artifact@v1 78 | with: 79 | name: TestFlight 80 | path: ${{ steps.assemble-release.outputs.release-dir }} 81 | 82 | 83 | -------------------------------------------------------------------------------- /.github/workflows/pr-comment.yml: -------------------------------------------------------------------------------- 1 | name: Comment on pull request 2 | on: 3 | workflow_run: 4 | workflows: ['build'] 5 | types: [completed] 6 | jobs: 7 | pr_comment: 8 | if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/github-script@v3 12 | with: 13 | # This snippet is public-domain, taken from 14 | # https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml 15 | script: | 16 | const {owner, repo} = context.repo; 17 | const run_id = ${{github.event.workflow_run.id}}; 18 | const pull_head_sha = '${{github.event.workflow_run.head_sha}}'; 19 | const pull_user_id = ${{github.event.sender.id}}; 20 | 21 | const issue_number = await (async () => { 22 | const pulls = await github.pulls.list({owner, repo}); 23 | for await (const {data} of github.paginate.iterator(pulls)) { 24 | for (const pull of data) { 25 | if (pull.head.sha === pull_head_sha && pull.user.id === pull_user_id) { 26 | return pull.number; 27 | } 28 | } 29 | } 30 | })(); 31 | if (issue_number) { 32 | core.info(`Using pull request ${issue_number}`); 33 | } else { 34 | return core.error(`No matching pull request found`); 35 | } 36 | 37 | const {data: {artifacts}} = await github.actions.listWorkflowRunArtifacts({owner, repo, run_id}); 38 | if (!artifacts.length) { 39 | return core.error(`No artifacts found`); 40 | } 41 | let body = `Download the artifacts for this pull request:\n`; 42 | for (const art of artifacts) { 43 | body += `\n* [${art.name}.zip](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`; 44 | } 45 | 46 | const {data: comments} = await github.issues.listComments({repo, owner, issue_number}); 47 | const existing_comment = comments.find((c) => c.user.login === 'github-actions[bot]'); 48 | if (existing_comment) { 49 | core.info(`Updating comment ${existing_comment.id}`); 50 | await github.issues.updateComment({repo, owner, comment_id: existing_comment.id, body}); 51 | } else { 52 | core.info(`Creating a comment`); 53 | await github.issues.createComment({repo, owner, issue_number, body}); 54 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: tagged-release 2 | 3 | # Controls when the action will run. 4 | on: 5 | release: 6 | types: [published] 7 | 8 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 9 | jobs: 10 | tagged-release: 11 | name: "Tagged Release" 12 | # The type of runner that the job will run on 13 | runs-on: ubuntu-latest 14 | 15 | # Steps represent a sequence of tasks that will be executed as part of the job 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v2 19 | with: 20 | fetch-depth: 100 21 | 22 | - name: Download required assemblies 23 | id: download-assemblies 24 | shell: bash 25 | env: 26 | KSP_ZIP_PASSWORD: ${{ secrets.KSP_ZIP_PASSWORD }} 27 | run: | 28 | curl https://ksp-ro.s3-us-west-2.amazonaws.com/KSPAssemblies-1.12.zip --output /tmp/bins.zip 29 | KSP_DLL_PATH="/opt/ksp/assembly" 30 | echo "::set-output name=ksp-dll-path::${KSP_DLL_PATH}" 31 | mkdir -p "${KSP_DLL_PATH}" 32 | unzip -P "${KSP_ZIP_PASSWORD}" '/tmp/bins.zip' -d "${KSP_DLL_PATH}" 33 | rm '/tmp/bins.zip' 34 | 35 | - name: Build mod solution 36 | run: | 37 | rm -f ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/*.dll 38 | mkdir -p "${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/" 39 | msbuild /p:Configuration=Release /p:ReferencePath="${{ steps.download-assemblies.outputs.ksp-dll-path }}" TestFlight.sln 40 | cp -v ${GITHUB_WORKSPACE}/bin/Release/TestFlight.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlight.dll 41 | cp -v ${GITHUB_WORKSPACE}/TestFlightAPI/TestFlightAPI/bin/Release/TestFlightAPI.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlightAPI.dll 42 | cp -v ${GITHUB_WORKSPACE}/TestFlightCore/TestFlightCore/bin/Release/TestFlightCore.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlightCore.dll 43 | cp -v ${GITHUB_WORKSPACE}/TestFlightContracts/bin/Release/TestFlightContracts.dll ${GITHUB_WORKSPACE}/GameData/TestFlight/Plugins/TestFlightContracts.dll 44 | 45 | - name: Remove excess DLLs 46 | uses: KSP-RO/BuildTools/remove-excess-dlls@master 47 | with: 48 | path: ${GITHUB_WORKSPACE}/GameData/ 49 | 50 | - name: Setup python 51 | uses: actions/setup-python@v2 52 | 53 | - name: Make metadata 54 | run: | 55 | python ${GITHUB_WORKSPACE}/makeMeta.py ${{ github.event.release.tag_name }} 56 | 57 | - name: Assemble release 58 | id: assemble-release 59 | run: | 60 | RELEASE_DIR="${RUNNER_TEMP}/release" 61 | echo "Release dir: ${RELEASE_DIR}" 62 | echo "Release zip: ${RELEASE_DIR}/TestFlight-${{ github.event.release.tag_name }}.zip" 63 | mkdir -v "${RELEASE_DIR}" 64 | echo "::set-output name=release-dir::${RELEASE_DIR}" 65 | cp -v -R "${GITHUB_WORKSPACE}/GameData" "${RELEASE_DIR}" 66 | cp -v -R "${GITHUB_WORKSPACE}/TestFlight.version" "${RELEASE_DIR}/GameData/TestFlight/TestFlight.version" 67 | cd ${RELEASE_DIR} 68 | zip TestFlight-${{ github.event.release.tag_name }}.zip GameData GameData/TestFlight/* GameData/TestFlight/Plugins/TestFlight*.dll GameData/TestFlight/Resources/* GameData/TestFlight/Resources/Textures/* 69 | ls -lrt -d -1 "${RELEASE_DIR}"/{*,.*} 70 | 71 | - name: Upload package to release 72 | uses: actions/upload-release-asset@v1 73 | env: 74 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 75 | with: 76 | upload_url: ${{ github.event.release.upload_url }} 77 | asset_path: ${{ steps.assemble-release.outputs.release-dir }}/TestFlight-${{ github.event.release.tag_name }}.zip 78 | asset_name: TestFlight-${{ github.event.release.tag_name }}.zip 79 | asset_content_type: application/zip 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | *.userprefs 9 | *.vs/ 10 | 11 | # Build results 12 | [Dd]ebug/ 13 | [Dd]ebugPublic/ 14 | [Rr]elease/ 15 | x64/ 16 | build/ 17 | bld/ 18 | [Bb]in/ 19 | [Oo]bj/ 20 | *.dll 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | # Build Results of an ATL Project 31 | [Dd]ebugPS/ 32 | [Rr]eleasePS/ 33 | dlldata.c 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opensdf 68 | *.sdf 69 | *.cachefile 70 | 71 | # Visual Studio profiler 72 | *.psess 73 | *.vsp 74 | *.vspx 75 | 76 | # TFS 2012 Local Workspace 77 | $tf/ 78 | 79 | # Guidance Automation Toolkit 80 | *.gpState 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper*/ 84 | *.[Rr]e[Ss]harper 85 | *.DotSettings.user 86 | 87 | # JustCode is a .NET coding addin-in 88 | .JustCode 89 | 90 | # TeamCity is a build add-in 91 | _TeamCity* 92 | 93 | # DotCover is a Code Coverage Tool 94 | *.dotCover 95 | 96 | # NCrunch 97 | *.ncrunch* 98 | _NCrunch_* 99 | .*crunch*.local.xml 100 | 101 | # MightyMoose 102 | *.mm.* 103 | AutoTest.Net/ 104 | 105 | # Web workbench (sass) 106 | .sass-cache/ 107 | 108 | # Installshield output folder 109 | [Ee]xpress/ 110 | 111 | # DocProject is a documentation generator add-in 112 | DocProject/buildhelp/ 113 | DocProject/Help/*.HxT 114 | DocProject/Help/*.HxC 115 | DocProject/Help/*.hhc 116 | DocProject/Help/*.hhk 117 | DocProject/Help/*.hhp 118 | DocProject/Help/Html2 119 | DocProject/Help/html 120 | 121 | # Click-Once directory 122 | publish/ 123 | 124 | # Publish Web Output 125 | *.[Pp]ublish.xml 126 | *.azurePubxml 127 | 128 | # NuGet Packages Directory 129 | packages/ 130 | ## TODO: If the tool you use requires repositories.config uncomment the next line 131 | #!packages/repositories.config 132 | 133 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 134 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) 135 | !packages/build/ 136 | 137 | # Windows Azure Build Output 138 | csx/ 139 | *.build.csdef 140 | 141 | # Windows Store app package directory 142 | AppPackages/ 143 | 144 | # Others 145 | sql/ 146 | *.Cache 147 | ClientBin/ 148 | [Ss]tyle[Cc]op.* 149 | ~$* 150 | *~ 151 | *.dbmdl 152 | *.dbproj.schemaview 153 | *.pfx 154 | *.publishsettings 155 | node_modules/ 156 | 157 | # RIA/Silverlight projects 158 | Generated_Code/ 159 | 160 | # Backup & report files from converting an old project file to a newer 161 | # Visual Studio version. Backup files are not needed, because we have git ;-) 162 | _UpgradeReport_Files/ 163 | Backup*/ 164 | UpgradeLog*.XML 165 | UpgradeLog*.htm 166 | 167 | # SQL Server files 168 | *.mdf 169 | *.ldf 170 | 171 | # Business Intelligence projects 172 | *.rdl.data 173 | *.bim.layout 174 | *.bim_*.settings 175 | 176 | # Microsoft Fakes 177 | FakesAssemblies/ 178 | 179 | # ========================= 180 | # Operating System Files 181 | # ========================= 182 | 183 | # OSX 184 | # ========================= 185 | 186 | .DS_Store 187 | .AppleDouble 188 | .LSOverride 189 | 190 | # Icon must ends with two \r. 191 | Icon 192 | 193 | 194 | # Thumbnails 195 | ._* 196 | 197 | # Files that might appear on external disk 198 | .Spotlight-V100 199 | .Trashes 200 | 201 | # Windows 202 | # ========================= 203 | 204 | # Windows image file caches 205 | Thumbs.db 206 | ehthumbs.db 207 | 208 | # Folder config file 209 | Desktop.ini 210 | 211 | # Recycle Bin used on file shares 212 | $RECYCLE.BIN/ 213 | 214 | # Windows Installer files 215 | *.cab 216 | *.msi 217 | *.msm 218 | *.msp 219 | 220 | TestFlight.userprefs 221 | 222 | *.userprefs 223 | -------------------------------------------------------------------------------- /.idea/.idea.TestFlight/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /.idea.TestFlight.iml 6 | /modules.xml 7 | /contentModel.xml 8 | /projectSettingsUpdater.xml 9 | # Datasource local storage ignored files 10 | /../../../../../../:\Developer\TestFlight\.idea\.idea.TestFlight\.idea/dataSources/ 11 | /dataSources.local.xml 12 | # Editor-based HTTP Client requests 13 | /httpRequests/ 14 | -------------------------------------------------------------------------------- /CachedEngineState.cs: -------------------------------------------------------------------------------- 1 | namespace TestFlight 2 | { 3 | public class CachedEngineState : IConfigNode 4 | { 5 | [Persistent] public bool allowShutdown; 6 | [Persistent] public bool allowRestart; 7 | [Persistent] public int numIgnitions; 8 | 9 | public CachedEngineState() { } 10 | 11 | public CachedEngineState(ConfigNode node) 12 | { 13 | Load(node); 14 | } 15 | 16 | public CachedEngineState(EngineModuleWrapper engine) 17 | { 18 | allowShutdown = engine.allowShutdown; 19 | allowRestart = engine.allowRestart; 20 | numIgnitions = engine.GetIgnitionCount(); 21 | } 22 | 23 | public void Load(ConfigNode node) 24 | { 25 | ConfigNode.LoadObjectFromConfig(this, node); 26 | } 27 | 28 | public void Save(ConfigNode node) 29 | { 30 | ConfigNode.CreateConfigFromObject(this, node); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EngineRunData.cs: -------------------------------------------------------------------------------- 1 | namespace TestFlight 2 | { 3 | public class EngineRunData : IConfigNode 4 | { 5 | public uint id; 6 | public bool hasBeenRun; 7 | public float timeSinceLastShutdown; 8 | 9 | public EngineRunData(uint id) 10 | { 11 | this.id = id; 12 | } 13 | 14 | public EngineRunData(ConfigNode node) 15 | { 16 | Load(node); 17 | } 18 | 19 | public void Load(ConfigNode node) 20 | { 21 | node.TryGetValue("id", ref id); 22 | node.TryGetValue("hasBeenRun", ref hasBeenRun); 23 | node.TryGetValue("timeSinceLastShutdown", ref timeSinceLastShutdown); 24 | } 25 | 26 | public void Save(ConfigNode node) 27 | { 28 | node.AddValue("id", id); 29 | node.AddValue("hasBeenRun", hasBeenRun); 30 | node.AddValue("timeSinceLastShutdown", timeSinceLastShutdown); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ExampleConfig.cfg: -------------------------------------------------------------------------------- 1 | MODULE 2 | { 3 | name = FlightDataRecorder 4 | FLIGHTDATA 5 | { 6 | initialDataDeepSpace = 0 7 | FLIGHTDATA_BODY 8 | { 9 | bodyName = Kerbin 10 | initialDataAtmosphere = 500 11 | initialDataSpace = 100 12 | } 13 | } 14 | } 15 | MODULE 16 | { 17 | name = TestFlight_Reliability 18 | realiabilityFactor = 3 19 | reliabilityMultiplier = 2 20 | minReliabilityDeepSpace = 10 21 | maxReliabilityDeepSpace = 90 22 | RELIABILITY_BODY 23 | { 24 | bodyName = Kerbin 25 | minReliabilityAtmosphere = 30 26 | maxReliabilityAtmosphere = 99 27 | minReliabilitySpacd = 20 28 | maxReliabilitySpacd = 95 29 | } 30 | } 31 | MODULE 32 | { 33 | name = TestFlightFailure_DisableGimbal 34 | type = Mechanical 35 | severity = Major 36 | probability = 50 37 | REPAIR 38 | { 39 | canBeRepairedOnLanded = true 40 | canBeRepairdOnEVA = true 41 | canBeRepairdOnSplashed = false 42 | spareParts = 5 43 | time = 50 44 | repairChance = 90 45 | } 46 | } 47 | MODULE 48 | { 49 | name = TestFlightFailure_Explode 50 | type = Mechanical 51 | severity = Major 52 | probability = 50 53 | } 54 | MODULE 55 | { 56 | name = TestFlightFailure_Disable 57 | type = Mechanical 58 | severity = Major 59 | probability = 20 60 | REPAIR 61 | { 62 | canBeRepairedOnLanded = true 63 | canBeRepairdOnEVA = true 64 | canBeRepairdOnSplashed = false 65 | spareParts = 10 66 | time = 100 67 | repairChance = 80 68 | } 69 | } 70 | MODULE 71 | { 72 | name = TestFlightFailure_Disable 73 | type = Software 74 | severity = Major 75 | probability = 30 76 | REPAIR 77 | { 78 | canBeRepairedByRemote = true 79 | dataScale = 1 80 | dataSize = 20 81 | repairChance = 90 82 | } 83 | } -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_Avionics.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailureBase_Avionics : TestFlightFailureBase 11 | { 12 | public enum FailedState 13 | { 14 | Pitch = 0, 15 | Roll = 1, 16 | Yaw = 2, 17 | Rotate = 3, 18 | TranX = 4, 19 | TranY = 5, 20 | TranZ = 6, 21 | Translate = 7 22 | } 23 | 24 | [KSPField] 25 | public bool isFlyByWire = false; 26 | 27 | public FailedState failedState; 28 | public float failedValue; 29 | 30 | public override void DoFailure() 31 | { 32 | base.DoFailure(); 33 | if (base.vessel != null) 34 | { 35 | Random ran = new Random(); 36 | this.failedValue = 1f - (float)Math.Pow(ran.NextDouble(), 2); 37 | this.failedState = (FailedState)ran.Next(0, 8); 38 | base.vessel.OnFlyByWire -= this.OnFlyByWire; 39 | base.vessel.OnFlyByWire += this.OnFlyByWire; 40 | } 41 | 42 | } 43 | public override float DoRepair() 44 | { 45 | base.DoRepair(); 46 | if (base.vessel != null) 47 | { 48 | base.vessel.OnFlyByWire -= this.OnFlyByWire; 49 | } 50 | return 0f; 51 | } 52 | public virtual void OnFlyByWire(FlightCtrlState s) 53 | { 54 | if (base.vessel == null || base.vessel != FlightGlobals.ActiveVessel || base.part.isControlSource != Vessel.ControlLevel.FULL) 55 | { 56 | return; 57 | } 58 | switch (this.failedState) 59 | { 60 | case FailedState.Pitch: 61 | s.pitch = Calculate(s.pitch); 62 | break; 63 | case FailedState.Roll: 64 | s.roll = Calculate(s.roll); 65 | break; 66 | case FailedState.Yaw: 67 | s.yaw = Calculate(s.yaw); 68 | break; 69 | case FailedState.Rotate: 70 | s.pitch = Calculate(s.pitch); 71 | s.roll = Calculate(s.roll); 72 | s.yaw = Calculate(s.yaw); 73 | break; 74 | case FailedState.TranX: 75 | s.X = Calculate(s.X); 76 | break; 77 | case FailedState.TranY: 78 | s.Y = Calculate(s.Y); 79 | break; 80 | case FailedState.TranZ: 81 | s.Z = Calculate(s.Z); 82 | break; 83 | case FailedState.Translate: 84 | s.X = Calculate(s.X); 85 | s.Y = Calculate(s.Y); 86 | s.Z = Calculate(s.Z); 87 | break; 88 | } 89 | } 90 | 91 | public virtual float Calculate(float value) 92 | { 93 | return value; 94 | } 95 | public void OnDestroy() 96 | { 97 | if (base.vessel != null) 98 | { 99 | base.vessel.OnFlyByWire -= this.OnFlyByWire; 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_Docking.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using KSP; 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailureBase_Docking : TestFlightFailureBase 11 | { 12 | protected ModuleDockingNode module; 13 | public override void OnStart(PartModule.StartState state) 14 | { 15 | base.OnStart(state); 16 | this.module = base.part.FindModuleImplementing(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_FARCtrlSrf.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight 8 | { 9 | public class TestFlightFailureBase_FARCtrlSrf : TestFlightFailureBase 10 | { 11 | protected PartModule module; 12 | 13 | public override void OnStart(PartModule.StartState state) 14 | { 15 | base.OnStart(state); 16 | this.module = base.part.Modules["FARControllableSurface"]; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_Generic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Reflection; 6 | 7 | using TestFlightAPI; 8 | 9 | namespace TestFlight 10 | { 11 | public class TestFlightFailureBase_Generic : TestFlightFailureBase 12 | { 13 | protected string modName = ""; 14 | protected PartModule module; 15 | public override void OnStart(PartModule.StartState state) 16 | { 17 | base.OnStart(state); 18 | this.module = base.part.Modules[this.modName]; 19 | } 20 | public void SetValue(string fieldName, object value) 21 | { 22 | if (this.module != null) 23 | { 24 | FieldInfo field = this.module.GetType().GetField(fieldName); 25 | if (field != null) 26 | { 27 | field.SetValue(module, value); 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_Gimbal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | using KSP; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailureBase_Gimbal : TestFlightFailureBase 11 | { 12 | [KSPField(isPersistant = false)] 13 | public string gimbalTransformName = "RANDOM"; 14 | 15 | protected ModuleGimbal module; 16 | 17 | public override void OnStart(PartModule.StartState state) 18 | { 19 | base.OnStart(state); 20 | List gimbals = base.part.Modules.OfType().ToList(); 21 | if (this.gimbalTransformName != "RANDOM") 22 | { 23 | for (int i = 0; i < gimbals.Count; i++) 24 | { 25 | ModuleGimbal gimbal = gimbals[i]; 26 | if (gimbal.gimbalTransformName == this.gimbalTransformName && !gimbal.gimbalLock && gimbal.gimbalRange > 0f) 27 | { 28 | this.module = gimbal; 29 | return; 30 | } 31 | } 32 | gimbalTransformName = "RANDOM"; 33 | } 34 | if (this.gimbalTransformName == "RANDOM") 35 | { 36 | List valid = new List(); 37 | for (int i = 0; i < gimbals.Count; i++) 38 | { 39 | ModuleGimbal gimbal = gimbals[i]; 40 | if (!gimbal.gimbalLock && gimbal.gimbalRange > 0f) 41 | { 42 | valid.Add(gimbal); 43 | } 44 | } 45 | int roll = UnityEngine.Random.Range(0, valid.Count); 46 | module = valid[roll]; 47 | gimbalTransformName = module.gimbalTransformName; 48 | } 49 | } 50 | public override void DoFailure() 51 | { 52 | base.DoFailure(); 53 | } 54 | public override float DoRepair() 55 | { 56 | return base.DoRepair(); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_Light.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailureBase_Light : TestFlightFailureBase 11 | { 12 | protected ModuleLight module; 13 | 14 | public override void OnAwake() 15 | { 16 | base.OnAwake(); 17 | this.module = base.part.FindModuleImplementing(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_ReactionWheel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight 8 | { 9 | public class TestFlightFailureBase_ReactionWheel : TestFlightFailureBase 10 | { 11 | protected ModuleReactionWheel module; 12 | public override void OnStart(PartModule.StartState state) 13 | { 14 | base.OnStart(state); 15 | this.module = base.part.FindModuleImplementing(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_Science.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailureBase_Science : TestFlightFailureBase 11 | { 12 | [KSPField] 13 | public string experimentID = ""; 14 | 15 | protected ModuleScienceExperiment module; 16 | public override void OnAwake() 17 | { 18 | base.OnAwake(); 19 | List list = base.part.Modules.OfType().ToList(); 20 | if (list != null) 21 | { 22 | for (int i=0; i(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Failure Bases/TestFlightFailureBase_Wheel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | using ModuleWheels; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailureBase_Wheel : TestFlightFailureBase 11 | { 12 | protected ModuleWheelBase wheelBase; 13 | protected ModuleWheelSteering wheelSteering; 14 | protected ModuleWheelBrakes wheelBrakes; 15 | protected ModuleWheelMotor wheelMotor; 16 | 17 | public override void OnStart(StartState state) 18 | { 19 | base.OnStart(state); 20 | this.wheelBase = base.part.FindModuleImplementing(); 21 | this.wheelSteering = base.part.FindModuleImplementing(); 22 | this.wheelBrakes = base.part.FindModuleImplementing(); 23 | this.wheelMotor = base.part.FindModuleImplementing(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AblatorCover.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | using KSP; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailure_AblatorCover : TestFlightFailureBase 11 | { 12 | [KSPField] 13 | public int minDegradation = 5; 14 | [KSPField] 15 | public int maxDegradation = 10; 16 | 17 | private double baseConductivity; 18 | private double ablatorConductivity; 19 | private ModuleAblator ablator; 20 | public override void OnStart(StartState state) 21 | { 22 | base.OnStart(state); 23 | this.baseConductivity = this.part.heatConductivity; 24 | this.ablator = this.part.FindModuleImplementing(); 25 | if (this.ablator != null) 26 | { 27 | this.ablatorConductivity = this.ablator.reentryConductivity; 28 | } 29 | } 30 | public override void DoFailure() 31 | { 32 | base.DoFailure(); 33 | if (this.ablator != null) 34 | { 35 | double total = this.baseConductivity - this.ablatorConductivity; 36 | double remains = total - (this.ablator.reentryConductivity - this.ablatorConductivity); 37 | if (remains > 0) 38 | { 39 | Random ran = new Random(); 40 | double degrade = (double)ran.Next(this.minDegradation, this.maxDegradation + 1) * 0.01; 41 | this.ablator.reentryConductivity += Math.Min(remains, total * degrade); 42 | if (this.ablator.ablativeResource != string.Empty && base.part.Resources.Contains(this.ablator.ablativeResource)) 43 | { 44 | PartResource res = base.part.Resources[this.ablator.ablativeResource]; 45 | res.amount -= res.amount * degrade; 46 | } 47 | } 48 | } 49 | } 50 | public override float DoRepair() 51 | { 52 | base.DoRepair(); 53 | if (this.ablator != null) 54 | { 55 | this.ablator.reentryConductivity = this.ablatorConductivity; 56 | } 57 | return 0F; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_Animation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | using KSP; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailure_Animation : TestFlightFailureBase 11 | { 12 | [KSPField] 13 | public string animationName = "ALL"; 14 | public override void DoFailure() 15 | { 16 | base.DoFailure(); 17 | SetState(false); 18 | } 19 | public override float DoRepair() 20 | { 21 | base.DoRepair(); 22 | SetState(true); 23 | return 0F; 24 | } 25 | private void SetState(bool state) 26 | { 27 | List anims = this.part.Modules.OfType().ToList(); 28 | for (int i = 0; i < anims.Count; i++) 29 | { 30 | if (this.animationName == "ALL" || this.animationName == anims[i].animationName) 31 | { 32 | anims[i].allowManualControl = state; 33 | anims[i].enabled = state; 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsAxis.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_AvionicsAxis : TestFlightFailureBase_Avionics 9 | { 10 | public override float Calculate(float value) 11 | { 12 | return 0; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsClamp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using UnityEngine; 7 | 8 | namespace TestFlight.Failure_Modules 9 | { 10 | public class TestFlightFailure_AvionicsClamp : TestFlightFailureBase_Avionics 11 | { 12 | public override float Calculate(float value) 13 | { 14 | return Mathf.Clamp(value, -this.failedValue, this.failedValue); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsDeadzone.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_AvionicsDeadzone : TestFlightFailureBase_Avionics 9 | { 10 | private float deadStart; 11 | private float deadEnd; 12 | public override void DoFailure() 13 | { 14 | base.DoFailure(); 15 | Random ran = new Random(); 16 | float range = (float)ran.NextDouble() * 0.25f; 17 | float center = (float)ran.NextDouble() * 2 - 1; 18 | this.deadStart = Math.Max(center - range, -1f); 19 | this.deadEnd = Math.Min(center + range, 1f); 20 | } 21 | public override float Calculate(float value) 22 | { 23 | if (value > this.deadStart && value < this.deadEnd) 24 | { 25 | return 0; 26 | } 27 | return value; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsGlitch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | //using UnityEngine; 7 | 8 | namespace TestFlight.Failure_Modules 9 | { 10 | public class TestFlightFailure_AvionicsGlitch : TestFlightFailureBase_Avionics 11 | { 12 | [KSPField] 13 | public float maxDeadtime = 1f; 14 | [KSPField] 15 | public float maxWorkTime = 1f; 16 | 17 | private float currentInterval = 0; 18 | private float currentTime = 0; 19 | private bool state = false; 20 | private Random random; 21 | 22 | public override void DoFailure() 23 | { 24 | base.DoFailure(); 25 | this.random = new Random(); 26 | } 27 | public override float Calculate(float value) 28 | { 29 | this.currentTime = this.currentTime + UnityEngine.Time.deltaTime; 30 | if (this.currentTime > this.currentInterval) 31 | { 32 | this.state = !this.state; 33 | this.currentTime = 0; 34 | this.currentInterval = (1 - (float)Math.Pow(this.random.NextDouble(), 2)); 35 | if (this.state) 36 | { 37 | this.currentInterval = this.currentInterval * this.maxWorkTime; 38 | } 39 | else 40 | { 41 | this.currentInterval = this.currentInterval * this.maxDeadtime; 42 | } 43 | } 44 | if (!this.state) 45 | { 46 | return 0; 47 | } 48 | return value; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsInvert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_AvionicsInvert : TestFlightFailureBase_Avionics 9 | { 10 | public override float Calculate(float value) 11 | { 12 | return -value; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsPartial.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_AvionicsPartial : TestFlightFailureBase_Avionics 9 | { 10 | public override float Calculate(float value) 11 | { 12 | return value * base.failedValue; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsThrustJam.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight.Failure_Modules 9 | { 10 | public class TestFlightFailure_AvionicsThrustJam : TestFlightFailureBase 11 | { 12 | [KSPField(isPersistant = true)] 13 | public float throttle; 14 | 15 | public override void DoFailure() 16 | { 17 | base.DoFailure(); 18 | if (base.vessel != null && base.part != null && base.vessel.referenceTransformId == base.part.flightID) 19 | { 20 | base.vessel.OnFlyByWire -= this.OnFlyByWire; 21 | base.vessel.OnFlyByWire += this.OnFlyByWire; 22 | this.throttle = base.vessel.ctrlState.mainThrottle; 23 | } 24 | } 25 | public override float DoRepair() 26 | { 27 | base.DoRepair(); 28 | if (base.vessel != null) 29 | { 30 | base.vessel.OnFlyByWire -= this.OnFlyByWire; 31 | } 32 | return 0f; 33 | } 34 | public void OnFlyByWire(FlightCtrlState s) 35 | { 36 | s.mainThrottle = this.throttle; 37 | } 38 | public void OnDestroy() 39 | { 40 | if (base.vessel != null) 41 | { 42 | base.vessel.OnFlyByWire -= this.OnFlyByWire; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_AvionicsTotal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_AvionicsTotal : TestFlightFailureBase_Avionics 9 | { 10 | public override void OnFlyByWire(FlightCtrlState s) 11 | { 12 | if (base.vessel == null || base.vessel != FlightGlobals.ActiveVessel || base.part.isControlSource != Vessel.ControlLevel.FULL) 13 | { 14 | s.pitch = 0; 15 | s.roll = 0; 16 | s.yaw = 0; 17 | s.X = 0; 18 | s.Y = 0; 19 | s.Z = 0; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_DockingClamp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight 7 | { 8 | public class TestFlightFailure_DockingClamp : TestFlightFailureBase_Docking 9 | { 10 | public override void DoFailure() 11 | { 12 | base.DoFailure(); 13 | if (base.module != null) 14 | { 15 | if (base.module.Events["Decouple"].active) 16 | { 17 | base.module.Decouple(); 18 | } 19 | else if (base.module.Events["Undock"].active) 20 | { 21 | base.module.Undock(); 22 | } 23 | } 24 | } 25 | public override bool CanAttemptRepair() 26 | { 27 | return false; 28 | } 29 | public override float DoRepair() 30 | { 31 | return -1f; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_DockingFeed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight 7 | { 8 | public class TestFlightFailure_DockingFeed : TestFlightFailureBase_Docking 9 | { 10 | private bool state = false; 11 | public override void DoFailure() 12 | { 13 | base.DoFailure(); 14 | this.state = base.module.Events["DisableXFeed"].active; 15 | base.module.Events["DisableXFeed"].active = false; 16 | base.module.Events["EnableXFeed"].active = false; 17 | base.part.fuelCrossFeed = false; 18 | } 19 | public override float DoRepair() 20 | { 21 | base.DoRepair(); 22 | base.module.Events["DisableXFeed"].active = this.state; 23 | base.module.Events["EnableXFeed"].active = !this.state; 24 | base.part.fuelCrossFeed = this.state; 25 | return 0f; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_EngineCoolant.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_EngineCoolant : TestFlightFailure_Engine 9 | { 10 | [KSPField] 11 | public float heatMultiplier = 3.0F; 12 | 13 | public override void OnStart(StartState state) 14 | { 15 | base.OnStart(state); 16 | base.Startup(); 17 | } 18 | 19 | public override void DoFailure() 20 | { 21 | base.DoFailure(); 22 | foreach (EngineHandler engine in engines) 23 | { 24 | ModuleEngines module = (ModuleEngines)engine.engine.Module; 25 | if (module != null) 26 | { 27 | module.heatProduction *= heatMultiplier; 28 | } 29 | } 30 | } 31 | public override float DoRepair() 32 | { 33 | base.DoRepair(); 34 | foreach (EngineHandler engine in engines) 35 | { 36 | ModuleEngines module = (ModuleEngines)engine.engine.Module; 37 | if (module != null) 38 | { 39 | module.heatProduction /= heatMultiplier; 40 | } 41 | } 42 | return 0f; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_FARCtrlSrfGlitch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_FARCtrlSrfGlitch : TestFlightFailureBase_FARCtrlSrf 9 | { 10 | public override void DoFailure() 11 | { 12 | base.DoFailure(); 13 | Random ran = new Random(); 14 | int roll = ran.Next(1, 4); 15 | BaseField mf = base.module.Fields["flapDeflectionLevel"]; 16 | SetFlap(base.module, (mf.GetValue(mf.host) + roll) % 4); 17 | } 18 | public override float DoRepair() 19 | { 20 | base.DoRepair(); 21 | SetFlap(base.module, 2); 22 | for (int i = 0; i < base.part.symmetryCounterparts.Count; i++) 23 | { 24 | Part p = base.part.symmetryCounterparts[i]; 25 | for (int j = 0; j < p.Modules.Count; j++) 26 | { 27 | PartModule m = p.Modules[j]; 28 | if (m.moduleName == "FARControllableSurface") 29 | { 30 | SetFlap(m, 2); 31 | } 32 | } 33 | } 34 | return 0f; 35 | } 36 | private void SetFlap(PartModule m, int deflect) 37 | { 38 | BaseField mf = m.Fields["flapDeflectionLevel"]; 39 | mf.SetValue(deflect, mf.host); 40 | m.Events["DeflectMore"].active = deflect < 3; 41 | m.Events["DeflectLess"].active = deflect > 0; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_FARCtrlSrfMech.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_FARCtrlSrfMech : TestFlightFailureBase_FARCtrlSrf 9 | { 10 | [KSPField(isPersistant = true)] 11 | public float pitchaxis; 12 | [KSPField(isPersistant = true)] 13 | public float rollaxis; 14 | [KSPField(isPersistant = true)] 15 | public float yawaxis; 16 | [KSPField(isPersistant = true)] 17 | public float pitchaxisDueToAoA; 18 | [KSPField(isPersistant = true)] 19 | public float brakeRudder; 20 | [KSPField(isPersistant = true)] 21 | public float maxdeflect; 22 | 23 | public override void DoFailure() 24 | { 25 | base.DoFailure(); 26 | 27 | SetSymState(UI_Scene.Editor); 28 | SetField("pitchaxis", false, 0); 29 | SetField("rollaxis", false, 0); 30 | SetField("yawaxis", false, 0); 31 | SetField("pitchaxisDueToAoA", false, -100); 32 | SetField("brakeRudder", false, 0); 33 | SetField("maxdeflect", false, 40); 34 | } 35 | public override float DoRepair() 36 | { 37 | base.DoRepair(); 38 | SetSymState(UI_Scene.All); 39 | SetField("pitchaxis", true, this.pitchaxis); 40 | SetField("rollaxis", true, this.rollaxis); 41 | SetField("yawaxis", true, this.yawaxis); 42 | SetField("pitchaxisDueToAoA", true, this.pitchaxisDueToAoA); 43 | SetField("brakeRudder", true, this.brakeRudder); 44 | SetField("maxdeflect", true, this.maxdeflect); 45 | return 0f; 46 | } 47 | private void SetField(string name, bool state, float value) 48 | { 49 | BaseField mf = base.module.Fields[name]; 50 | BaseField tf = this.Fields[name]; 51 | UI_Scene ui = (state ? UI_Scene.All : UI_Scene.Editor); 52 | 53 | mf.uiControlFlight.affectSymCounterparts = ui; 54 | mf.guiActive = state; 55 | if (!state) 56 | { 57 | tf.SetValue(mf.GetValue(mf.host), tf.host); 58 | } 59 | mf.SetValue(value, mf.host); 60 | } 61 | private void SetSymState(UI_Scene state) 62 | { 63 | for (int i = 0; i < base.part.symmetryCounterparts.Count; i++) 64 | { 65 | Part p = base.part.symmetryCounterparts[i]; 66 | for (int j = 0; j < p.Modules.Count; j++) 67 | { 68 | PartModule m = p.Modules[j]; 69 | if (m.moduleName == "FARControllableSurface") 70 | { 71 | m.Fields["pitchaxis"].uiControlFlight.affectSymCounterparts = state; 72 | m.Fields["rollaxis"].uiControlFlight.affectSymCounterparts = state; 73 | m.Fields["yawaxis"].uiControlFlight.affectSymCounterparts = state; 74 | m.Fields["pitchaxisDueToAoA"].uiControlFlight.affectSymCounterparts = state; 75 | m.Fields["brakeRudder"].uiControlFlight.affectSymCounterparts = state; 76 | m.Fields["maxdeflect"].uiControlFlight.affectSymCounterparts = state; 77 | } 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_GimbalCenter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | using KSP; 7 | using UnityEngine; 8 | 9 | namespace TestFlight 10 | { 11 | public class TestFlightFailure_GimbalCenter : TestFlightFailureBase_Gimbal 12 | { 13 | private float baseRange = 10f; 14 | private List _initRots; 15 | 16 | private List initRots 17 | { 18 | get 19 | { 20 | if (this._initRots == null) 21 | { 22 | this._initRots = base.module.initRots; 23 | } 24 | return this._initRots; 25 | } 26 | } 27 | public override void OnStart(PartModule.StartState state) 28 | { 29 | base.OnStart(state); 30 | Part p = base.part.partInfo.partPrefab; 31 | List gimbals = p.Modules.OfType().ToList(); 32 | for (int i = 0; i < gimbals.Count; i++) 33 | { 34 | ModuleGimbal gimbal = gimbals[i]; 35 | if (gimbal.gimbalTransformName == base.gimbalTransformName) 36 | { 37 | this.baseRange = gimbal.gimbalRange; 38 | break; 39 | } 40 | } 41 | } 42 | public override void DoFailure() 43 | { 44 | base.DoFailure(); 45 | //initRots[0] = Quaternion. 46 | float angle1 = UnityEngine.Random.Range(-this.baseRange, this.baseRange); 47 | float angle2 = UnityEngine.Random.Range(-this.baseRange, this.baseRange); 48 | float range = this.baseRange - Math.Max(Math.Abs(angle1), Math.Abs(angle2)); 49 | for (int i = 0; i < base.module.initRots.Count; i++) 50 | { 51 | this.module.initRots[i] = Quaternion.AngleAxis(angle1, Vector3.forward) * Quaternion.AngleAxis(angle2, Vector3.left) * initRots[i]; 52 | } 53 | base.module.gimbalRange = range; 54 | } 55 | public override float DoRepair() 56 | { 57 | base.DoRepair(); 58 | base.module.initRots = this.initRots; 59 | base.module.gimbalRange = this.baseRange; 60 | return 0f; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_GimbalSpeed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UnityEngine; 6 | 7 | namespace TestFlight 8 | { 9 | public class TestFlightFailure_GimbalSpeed : TestFlightFailureBase_Gimbal 10 | { 11 | private float baseSpeed = 10.0f; 12 | public override void OnStart(PartModule.StartState state) 13 | { 14 | base.OnStart(state); 15 | Part p = base.part.partInfo.partPrefab; 16 | List gimbals = p.Modules.OfType().ToList(); 17 | for (int i = 0; i < gimbals.Count; i++) 18 | { 19 | ModuleGimbal g = gimbals[i]; 20 | if (g.gimbalTransformName == base.gimbalTransformName) 21 | { 22 | this.baseSpeed = g.gimbalResponseSpeed; 23 | break; 24 | } 25 | } 26 | } 27 | public override void DoFailure() 28 | { 29 | base.DoFailure(); 30 | base.module.gimbalResponseSpeed = UnityEngine.Random.Range(0, base.module.gimbalResponseSpeed); 31 | } 32 | public override float DoRepair() 33 | { 34 | base.DoRepair(); 35 | base.module.gimbalResponseSpeed = this.baseSpeed; 36 | return 0f; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_LightBroken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Failure_Modules 8 | { 9 | public class TestFlightFailure_LightBroken : TestFlightFailureBase_Light 10 | { 11 | public override void DoFailure() 12 | { 13 | base.DoFailure(); 14 | if (base.module != null) 15 | { 16 | if (this.module.isOn) 17 | { 18 | this.module.LightsOff(); 19 | } 20 | base.module.Events["LightsOff"].active = false; 21 | base.module.Events["LightsOn"].active = false; 22 | } 23 | } 24 | public override float DoRepair() 25 | { 26 | base.DoRepair(); 27 | if (base.module != null) 28 | { 29 | this.module.Events["LightsOn"].active = true; 30 | } 31 | return 0f; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_LightFlicker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using UnityEngine; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightFailure_LightFlicker : TestFlightFailureBase_Light 11 | { 12 | [KSPField] 13 | public float maxFlickerTime = 0.4f; 14 | [KSPField] 15 | public float minFlickerTime = 0.1f; 16 | 17 | private bool flicker = false; 18 | private bool state = false; 19 | private float interval; 20 | 21 | private System.Random random = new System.Random(); 22 | public override void DoFailure() 23 | { 24 | base.DoFailure(); 25 | this.flicker = true; 26 | } 27 | public override float DoRepair() 28 | { 29 | base.DoRepair(); 30 | this.flicker = false; 31 | SetState(base.module.isOn); 32 | return 0f; 33 | } 34 | public override void OnUpdate() 35 | { 36 | if (this.flicker && base.module != null && base.module.isOn) 37 | { 38 | this.interval -= Time.deltaTime; 39 | if (this.interval < 0) 40 | { 41 | SetState(!this.state); 42 | this.interval += ((float)random.NextDouble() * (this.maxFlickerTime - this.minFlickerTime)) + this.minFlickerTime; 43 | } 44 | } 45 | } 46 | 47 | public void SetState(bool newState) 48 | { 49 | this.state = newState; 50 | for (int i = 0; i < base.module.lights.Count; i++) 51 | { 52 | base.module.lights[i].enabled = this.state; 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_ReactionBroken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight 8 | { 9 | public class TestFlightFailure_ReactionBroken : TestFlightFailureBase_ReactionWheel 10 | { 11 | private ModuleReactionWheel.WheelState state; 12 | public override void DoFailure() 13 | { 14 | base.DoFailure(); 15 | this.state = base.module.wheelState; 16 | base.module.Events["OnToggle"].active = false; 17 | base.module.wheelState = ModuleReactionWheel.WheelState.Broken; 18 | } 19 | public override float DoRepair() 20 | { 21 | base.DoRepair(); 22 | base.module.Events["OnToggle"].active = true; 23 | base.module.wheelState = this.state; 24 | return 0f; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_ReactionTorque.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight 7 | { 8 | public class TestFlightFailure_ReactionTorque : TestFlightFailureBase_ReactionWheel 9 | { 10 | private float PitchTorque; 11 | private float RollTorque; 12 | private float YawTorque; 13 | private int working; 14 | public override void DoFailure() 15 | { 16 | base.DoFailure(); 17 | if (base.module != null) 18 | { 19 | this.PitchTorque = base.module.PitchTorque; 20 | this.RollTorque = base.module.RollTorque; 21 | this.YawTorque = base.module.YawTorque; 22 | this.working = 7; 23 | 24 | Random ran = new Random(); 25 | int axis = ran.Next(0, 3); 26 | float modifier; 27 | while ((this.working & 2 ^ axis) != 0) 28 | { 29 | this.working -= 2 ^ axis; 30 | modifier = ((float)ran.NextDouble() * 2f) - 1f; 31 | switch (axis) 32 | { 33 | case 0: //pitch 34 | base.module.PitchTorque = this.PitchTorque * modifier; 35 | break; 36 | case 1: //roll 37 | base.module.RollTorque = this.RollTorque * modifier; 38 | break; 39 | case 2: //yaw 40 | base.module.YawTorque = this.YawTorque * modifier; 41 | break; 42 | } 43 | axis = ran.Next(0, 6); //yes axis are only 0 1 2, but this lowers chance for a 2nd axis failure 44 | } 45 | } 46 | } 47 | public override float DoRepair() 48 | { 49 | base.DoRepair(); 50 | base.module.PitchTorque = this.PitchTorque; 51 | base.module.RollTorque = this.RollTorque; 52 | base.module.YawTorque = this.YawTorque; 53 | return 0f; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_RemoteBroken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight 7 | { 8 | public class TestFlightFailure_RemoteBroken : TestFlightFailureBase_Generic 9 | { 10 | public override void OnLoad(ConfigNode node) 11 | { 12 | base.OnLoad(node); 13 | this.modName = "ModuleRTAntenna"; 14 | } 15 | public override void DoFailure() 16 | { 17 | base.DoFailure(); 18 | base.SetValue("IsRTBroken", true); 19 | } 20 | public override float DoRepair() 21 | { 22 | base.DoRepair(); 23 | base.SetValue("IsRTBroken", false); 24 | return 0f; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_RemotePassiveBroken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight 7 | { 8 | public class TestFlightFailure_RemotePassiveBroken : TestFlightFailureBase_Generic 9 | { 10 | public override void OnLoad(ConfigNode node) 11 | { 12 | base.OnLoad(node); 13 | this.modName = "ModuleRTAntennaPassive"; 14 | } 15 | public override void DoFailure() 16 | { 17 | base.DoFailure(); 18 | base.SetValue("IsRTBroken", true); 19 | } 20 | public override float DoRepair() 21 | { 22 | base.DoRepair(); 23 | base.SetValue("IsRTBroken", false); 24 | return 0f; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_ResourcePump.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Failure_Modules 8 | { 9 | public class TestFlightFailure_ResourcePump : TestFlightFailureBase 10 | { 11 | [KSPField] 12 | public string resourceName = "ANY"; 13 | [KSPField] 14 | public string resourceBlacklist = ""; 15 | public override void DoFailure() 16 | { 17 | base.DoFailure(); 18 | SetState(PartResource.FlowMode.None); 19 | } 20 | public override float DoRepair() 21 | { 22 | base.DoRepair(); 23 | SetState(PartResource.FlowMode.Both); 24 | return 0f; 25 | } 26 | private void SetState(PartResource.FlowMode state) 27 | { 28 | List blacklist = this.resourceBlacklist.Split(',').ToList(); 29 | List valid = null; 30 | for (int i = 0; i < base.part.Resources.ToList().Count; i++) 31 | { 32 | PartResource res = base.part.Resources.ToList()[i]; 33 | if (!blacklist.Contains(res.resourceName) && res.info.resourceFlowMode != ResourceFlowMode.NO_FLOW) 34 | { 35 | if (this.resourceName == "ALL" || res.resourceName == this.resourceName) 36 | { 37 | res.flowMode = state; 38 | return; 39 | } 40 | else if (this.resourceName == "ANY") 41 | { 42 | if (valid == null) 43 | { 44 | valid = new List(); 45 | } 46 | valid.Add(res); 47 | } 48 | } 49 | } 50 | if (this.resourceName == "ANY" && valid != null) 51 | { 52 | Random ran = new Random(); 53 | int roll = ran.Next(0, valid.Count); 54 | valid[roll].flowMode = state; 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_ScienceBroken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_ScienceBroken : TestFlightFailureBase_Science 9 | { 10 | //private bool oldState; 11 | private int inter; 12 | private int exter; 13 | private string usage; 14 | 15 | public override void DoFailure() 16 | { 17 | base.DoFailure(); 18 | this.inter = this.module.usageReqMaskInternal; 19 | this.exter = this.module.usageReqMaskExternal; 20 | this.usage = this.module.usageReqMessage; 21 | 22 | this.module.usageReqMaskInternal = -1; 23 | this.module.usageReqMaskExternal = -1; 24 | this.module.usageReqMessage = "Science experiment inoperable: " + base.failureTitle; 25 | } 26 | public override float DoRepair() 27 | { 28 | base.DoRepair(); 29 | this.module.usageReqMaskInternal = this.inter; 30 | this.module.usageReqMaskExternal = this.exter; 31 | this.module.usageReqMessage = this.usage; 32 | return 0f; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_ScienceCollect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_ScienceCollect : TestFlightFailureBase_Science 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_ScienceXmit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_ScienceXmit : TestFlightFailureBase_Science 9 | { 10 | [KSPField(isPersistant = true)] 11 | public float xmit = -1f; 12 | 13 | public override void OnStart(PartModule.StartState state) 14 | { 15 | base.OnStart(state); 16 | if (this.xmit == -1f) 17 | { 18 | this.xmit = base.module.xmitDataScalar; 19 | } 20 | } 21 | public override void DoFailure() 22 | { 23 | base.DoFailure(); 24 | System.Random ran = new System.Random(); 25 | base.module.xmitDataScalar = (float)ran.NextDouble() * this.xmit; 26 | } 27 | public override float DoRepair() 28 | { 29 | base.DoRepair(); 30 | base.module.xmitDataScalar = this.xmit; 31 | return 0; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_SolarMech.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | using UnityEngine; 8 | using TestFlightAPI; 9 | 10 | namespace TestFlight.Failure_Modules 11 | { 12 | public class TestFlightFailure_SolarMech : TestFlightFailureBase_Solar 13 | { 14 | private ITestFlightCore core = null; 15 | private ModuleDeployableSolarPanel.DeployState panelState; 16 | private bool failureActive = false; 17 | public override void OnStart(StartState state) 18 | { 19 | base.OnStart(state); 20 | StartCoroutine("Attach"); 21 | } 22 | 23 | IEnumerator Attach() 24 | { 25 | while (this.part == null || this.part.Modules == null) 26 | yield return null; 27 | 28 | while (core == null) 29 | { 30 | core = TestFlightUtil.GetCore(this.part, Configuration); 31 | yield return null; 32 | } 33 | 34 | Startup(); 35 | } 36 | public void Startup() 37 | { 38 | 39 | this.panelState = base.module.deployState; 40 | if (this.panelState == ModuleDeployableSolarPanel.DeployState.EXTENDED) 41 | { 42 | core.EnableFailure("TestFlightFailure_SolarMechFail"); 43 | } 44 | else 45 | { 46 | core.DisableFailure("TestFlightFailure_SolarMechFail"); 47 | } 48 | } 49 | public override void OnUpdate() 50 | { 51 | if (this.panelState != base.module.deployState) 52 | { 53 | this.panelState = base.module.deployState; 54 | if (TestFlightEnabled && !base.part.ShieldedFromAirstream && (this.panelState == ModuleDeployableSolarPanel.DeployState.EXTENDED) != this.failureActive) 55 | { 56 | this.failureActive = !this.failureActive; 57 | if (this.failureActive) 58 | { 59 | core.EnableFailure("TestFlightFailure_SolarMechFail"); 60 | } 61 | else 62 | { 63 | core.DisableFailure("TestFlightFailure_SolarMechFail"); 64 | } 65 | } 66 | } 67 | } 68 | public override void DoFailure() 69 | { 70 | base.DoFailure(); 71 | base.module.breakPanels(); 72 | } 73 | public override bool CanAttemptRepair() 74 | { 75 | return false; 76 | } 77 | public override float DoRepair() 78 | { 79 | return -1f; 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_SolarTracking.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using KSP; 7 | 8 | namespace TestFlight.Failure_Modules 9 | { 10 | public class TestFlightFailure_SolarTracking : TestFlightFailureBase_Solar 11 | { 12 | private float trackingSpeed = 0f; 13 | public override void DoFailure() 14 | { 15 | base.DoFailure(); 16 | this.trackingSpeed = base.module.trackingSpeed; 17 | base.module.trackingSpeed = 0; 18 | } 19 | public override float DoRepair() 20 | { 21 | base.DoRepair(); 22 | base.module.trackingSpeed = this.trackingSpeed; 23 | return 0f; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_WheelBrake.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_WheelBrake : TestFlightFailureBase_Wheel 9 | { 10 | public override void DoFailure() 11 | { 12 | base.DoFailure(); 13 | base.wheelBrakes.Actions["BrakesAction"].active = false; 14 | } 15 | public override float DoRepair() 16 | { 17 | base.DoRepair(); 18 | base.wheelBrakes.Actions["BrakesAction"].active = true; 19 | return 0f; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_WheelMotor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_WheelMotor : TestFlightFailureBase_Wheel 9 | { 10 | private bool state; 11 | public override void DoFailure() 12 | { 13 | base.DoFailure(); 14 | this.state = base.wheelMotor.motorEnabled; 15 | base.wheelMotor.motorEnabled = false; 16 | base.wheelMotor.Events["EnableMotor"].active = false; 17 | base.wheelMotor.Events["DisableMotor"].active = false; 18 | 19 | } 20 | public override float DoRepair() 21 | { 22 | base.DoRepair(); 23 | base.wheelMotor.motorEnabled = state; 24 | base.wheelMotor.Events["EnableMotor"].active = state; 25 | base.wheelMotor.Events["DisableMotor"].active = !state; 26 | return 0f; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Failure Modules/TestFlightFailure_WheelSteer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestFlight.Failure_Modules 7 | { 8 | public class TestFlightFailure_WheelSteer : TestFlightFailureBase_Wheel 9 | { 10 | private bool state; 11 | public override void DoFailure() 12 | { 13 | base.DoFailure(); 14 | this.state = base.wheelSteering.steeringEnabled; 15 | base.wheelSteering.steeringEnabled = false; 16 | base.wheelSteering.Events["LockSteering"].active = false; 17 | base.wheelSteering.Events["UnlockSteering"].active = false; 18 | } 19 | public override float DoRepair() 20 | { 21 | base.DoRepair(); 22 | base.wheelSteering.steeringEnabled = this.state; 23 | base.wheelSteering.Events["LockSteering"].active = !this.state; 24 | base.wheelSteering.Events["UnlockSteering"].active = this.state; 25 | return 0f; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_DockingPort.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_DockingPort : FlightDataRecorderBase 10 | { 11 | [KSPField] 12 | public float duDock = 10f; 13 | [KSPField] 14 | public float duUndock = 10f; 15 | public override void OnStart(PartModule.StartState state) 16 | { 17 | base.OnStart(state); 18 | //GameEvents.onPartCouple.Add(OnDock); 19 | //GameEvents.onPartUndock.Add(OnUndock); 20 | } 21 | public override void OnAwake() 22 | { 23 | base.OnAwake(); 24 | } 25 | public override bool IsRecordingFlightData() 26 | { 27 | return false; 28 | } 29 | public override void OnUpdate() 30 | { 31 | return; 32 | } 33 | private void OnDock(GameEvents.FromToAction action) 34 | { 35 | 36 | } 37 | private void OnUndock(Part part) 38 | { 39 | //if (part == base.part) 40 | //{ 41 | // base.core.ModifyFlightData(duUndock, true); 42 | //} 43 | } 44 | void OnDestroy() 45 | { 46 | //GameEvents.onPartUndock.Remove(OnUndock); 47 | //GameEvents.onPartCouple.Remove(OnDock); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_FARCtrlSrf.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_FARCtrlSrf : FlightDataRecorderBase 10 | { 11 | private PartModule module; 12 | private BaseField fpitch; 13 | private BaseField froll; 14 | private BaseField fyaw; 15 | 16 | public override void OnStart(PartModule.StartState state) 17 | { 18 | base.OnStart(state); 19 | module = base.part.Modules["FARControllableSurface"]; 20 | fpitch = this.module.Fields["pitchaxis"]; 21 | froll = this.module.Fields["rollaxis"]; 22 | fyaw = this.module.Fields["yawaxis"]; 23 | } 24 | public override bool IsPartOperating() 25 | { 26 | if (base.part.ShieldedFromAirstream || base.vessel.atmDensity < 0.01) 27 | { 28 | return false; 29 | } 30 | if (Math.Abs(base.vessel.ctrlState.pitch) > 0.01 && fpitch.GetValue(fpitch.host) != 0) 31 | { 32 | return true; 33 | } 34 | if (Math.Abs(base.vessel.ctrlState.roll) > 0.01 && froll.GetValue(froll.host) != 0) 35 | { 36 | return true; 37 | } 38 | if (Math.Abs(base.vessel.ctrlState.yaw) > 0.01 && fyaw.GetValue(fyaw.host) != 0) 39 | { 40 | return true; 41 | } 42 | return false; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_HeatShield.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_HeatShield : FlightDataRecorderBase 10 | { 11 | //private ModuleAblator ablator; 12 | private double ablationTempThresh = 600f; 13 | public override void OnStart(PartModule.StartState state) 14 | { 15 | base.OnStart(state); 16 | ModuleAblator ablator = base.part.FindModuleImplementing(); 17 | this.ablationTempThresh = ablator.ablationTempThresh; 18 | } 19 | public override void OnAwake() 20 | { 21 | base.OnAwake(); 22 | } 23 | public override bool IsRecordingFlightData() 24 | { 25 | return base.part.skinTemperature > this.ablationTempThresh; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_Intake.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_Intake : FlightDataRecorderBase 10 | { 11 | private ModuleResourceIntake intake; 12 | public override void OnStart(PartModule.StartState state) 13 | { 14 | base.OnStart(state); 15 | intake = base.part.FindModuleImplementing(); 16 | } 17 | public override bool IsPartOperating() 18 | { 19 | if (this.intake.airFlow < 0.1f) 20 | { 21 | return false; 22 | } 23 | 24 | return true; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_Lights.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_Lights : FlightDataRecorderBase 10 | { 11 | private ModuleLight module; 12 | public override void OnStart(PartModule.StartState state) 13 | { 14 | base.OnStart(state); 15 | this.module = base.part.FindModuleImplementing(); 16 | } 17 | public override bool IsPartOperating() 18 | { 19 | return this.module.isOn; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_RCS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_RCS : FlightDataRecorderBase 10 | { 11 | private ModuleRCS rcs; 12 | 13 | public override void OnStart(PartModule.StartState state) 14 | { 15 | base.OnStart(state); 16 | this.rcs = base.part.FindModuleImplementing(); 17 | } 18 | public override bool IsPartOperating() 19 | { 20 | if (!this.rcs.isEnabled || base.part.ShieldedFromAirstream || !base.part.isControllable) 21 | { 22 | return false; 23 | } 24 | if (!base.vessel.ActionGroups[KSPActionGroup.RCS] || this.rcs.isJustForShow) 25 | { 26 | return false; 27 | } 28 | if (this.rcs.thrustForces.Count() == 0) 29 | { 30 | return false; 31 | } 32 | return true; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_RT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Reflection; 6 | 7 | using TestFlightAPI; 8 | 9 | namespace TestFlight.Flight_Recorders 10 | { 11 | public class FlightDataRecorder_RT : FlightDataRecorderBase 12 | { 13 | private PartModule module; 14 | private FieldInfo isActive; 15 | private FieldInfo isPowered; 16 | public override void OnAwake() 17 | { 18 | base.OnAwake(); 19 | this.module = base.part.Modules["ModuleRTAntenna"]; 20 | if (this.module != null) 21 | { 22 | this.isActive = this.module.GetType().GetField("IsRTActive"); 23 | this.isPowered = this.module.GetType().GetField("IsRTPowered"); 24 | } 25 | } 26 | public override bool IsPartOperating() 27 | { 28 | if (this.module != null && this.isActive != null && this.isPowered != null) 29 | { 30 | return (bool)isActive.GetValue(this.module) && (bool)isPowered.GetValue(this.module); 31 | } 32 | return false; 33 | } 34 | private void OnDestroy() 35 | { 36 | this.module = null; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_ReactionWheel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_ReactionWheel : FlightDataRecorderBase 10 | { 11 | private ModuleReactionWheel module; 12 | public override void OnStart(PartModule.StartState state) 13 | { 14 | base.OnStart(state); 15 | module = base.part.FindModuleImplementing(); 16 | } 17 | public override bool IsPartOperating() 18 | { 19 | if (!TestFlightEnabled || module == null) 20 | { 21 | return false; 22 | } 23 | if (module.wheelState != ModuleReactionWheel.WheelState.Active) 24 | { 25 | return false; 26 | } 27 | if (module.inputSum < 0.1) 28 | { 29 | return false; 30 | } 31 | 32 | return true; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_Science.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight.Flight_Recorders 9 | { 10 | public class FlightDataRecorder_Science : FlightDataRecorderBase 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_Solar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | 7 | namespace TestFlight.Flight_Recorders 8 | { 9 | public class FlightDataRecorder_Solar : FlightDataRecorderBase 10 | { 11 | private ModuleDeployableSolarPanel module; 12 | public override void OnStart(PartModule.StartState state) 13 | { 14 | base.OnStart(state); 15 | this.module = base.part.FindModuleImplementing(); 16 | } 17 | public override bool IsPartOperating() 18 | { 19 | if (base.part.ShieldedFromAirstream) 20 | { 21 | return false; 22 | } 23 | if (this.module.deployState == ModuleDeployableSolarPanel.DeployState.BROKEN || this.module.deployState == ModuleDeployableSolarPanel.DeployState.RETRACTED) 24 | { 25 | return false; 26 | } 27 | if (this.module.deployState == ModuleDeployableSolarPanel.DeployState.EXTENDED && this.module.flowRate < 0.01) 28 | { 29 | return false; 30 | } 31 | return true; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Flight Recorders/FlightDataRecorder_Wheels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using TestFlightAPI; 6 | using ModuleWheels; 7 | 8 | namespace TestFlight.Flight_Recorders 9 | { 10 | public class FlightDataRecorder_Wheels : FlightDataRecorderBase 11 | { 12 | private ModuleWheelSteering wheelSteering; 13 | private ModuleWheelBrakes wheelBrakes; 14 | private ModuleWheelBase wheel; 15 | private ModuleWheelMotor wheelMotor; 16 | public override void OnStart(PartModule.StartState state) 17 | { 18 | base.OnStart(state); 19 | wheel = base.part.FindModuleImplementing(); 20 | wheelSteering = base.part.FindModuleImplementing(); 21 | wheelBrakes = base.part.FindModuleImplementing(); 22 | wheelMotor = base.part.FindModuleImplementing(); 23 | } 24 | public override void OnAwake() 25 | { 26 | base.OnAwake(); 27 | } 28 | public override bool IsPartOperating() 29 | { 30 | bool isGrounded = wheel.isGrounded; 31 | 32 | if (!isGrounded) 33 | { 34 | return false; 35 | } 36 | 37 | if ((float)base.vessel.horizontalSrfSpeed > 0f) 38 | { 39 | if (this.wheelSteering.steeringEnabled && Math.Abs(this.wheelSteering.steeringInput) > 0f) 40 | { 41 | return true; 42 | } 43 | if (this.wheelBrakes.brakeInput < 0f) 44 | { 45 | return true; 46 | } 47 | if (wheelMotor.motorEnabled && Math.Abs(wheelMotor.driveOutput) > 0f) 48 | { 49 | return true; 50 | } 51 | } 52 | 53 | return false; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /FlightDataRecorder.cs: -------------------------------------------------------------------------------- 1 | using TestFlightAPI; 2 | 3 | namespace TestFlight 4 | { 5 | // Method for determing distance from kerbal to part 6 | // float kerbalDistanceToPart = Vector3.Distance(kerbal.transform.position, targetPart.collider.ClosestPointOnBounds(kerbal.transform.position)); 7 | 8 | public class FlightDataRecorder : FlightDataRecorderBase 9 | { 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /FlightDataRecorder_Engine.cs: -------------------------------------------------------------------------------- 1 | using TestFlightAPI; 2 | 3 | namespace TestFlight 4 | { 5 | public class FlightDataRecorder_Engine : FlightDataRecorderBase 6 | { 7 | private EngineModuleWrapper engine; 8 | 9 | public override void OnStart(StartState state) 10 | { 11 | base.OnStart(state); 12 | engine = new EngineModuleWrapper(); 13 | engine.Init(this.part); 14 | } 15 | 16 | public override bool IsPartOperating() 17 | { 18 | return base.IsPartOperating() && engine.IgnitionState == EngineModuleWrapper.EngineIgnitionState.IGNITED; 19 | } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /FlightDataRecorder_Resources.cs: -------------------------------------------------------------------------------- 1 | using TestFlightAPI; 2 | 3 | namespace TestFlight 4 | { 5 | public class FlightDataRecorder_Resources : FlightDataRecorderBase 6 | { 7 | [KSPField] 8 | public double emptyThreshold = 0.1; 9 | 10 | public override bool IsRecordingFlightData() 11 | { 12 | // base checks: TF enabled, PartModule isEnabled, IsPartOperating() and Vessel.situation 13 | if (base.IsRecordingFlightData()) 14 | { 15 | foreach (PartResource resource in this.part.Resources) 16 | { 17 | if (resource.amount > emptyThreshold) 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /GameData/TestFlight/Config/ignore.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Config/ignore.txt -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/AppLauncherIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/AppLauncherIcon.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/ChevronDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/ChevronDown.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/ChevronLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/ChevronLeft.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/ChevronRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/ChevronRight.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/ChevronUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/ChevronUp.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/img_PanelBack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/img_PanelBack.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/img_PanelBack_Trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/img_PanelBack_Trans.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/img_PanelSolarizedDark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/img_PanelSolarizedDark.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/img_PartWindowHead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/img_PartWindowHead.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/img_SeparatorHorizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/img_SeparatorHorizontal.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/img_SeparatorVertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/img_SeparatorVertical.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/tex_Box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/tex_Box.png -------------------------------------------------------------------------------- /GameData/TestFlight/Resources/Textures/tex_BoxUnity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSP-RO/TestFlight/776c9f38d32c4f1b9a47905cc0573e0c530efb2d/GameData/TestFlight/Resources/Textures/tex_BoxUnity.png -------------------------------------------------------------------------------- /GameData/TestFlight/TestFlight.version: -------------------------------------------------------------------------------- 1 | { 2 | "NAME": "TestFlight", 3 | "URL": "https://raw.githubusercontent.com/KSP-RO/TestFlight/master/GameData/TestFlight/TestFlight.version", 4 | "CHANGE_LOG_URL": "https://raw.githubusercontent.com/KSP-RO/TestFlight/master/RELEASE_NOTES_RAW.txt", 5 | "KSP_VERSION": 6 | { 7 | "MAJOR": 1, 8 | "MINOR": 8, 9 | "PATCH": 1 10 | }, 11 | "VERSION": 12 | { 13 | "MAJOR": 2, 14 | "MINOR": 0, 15 | "PATCH": 0, 16 | "BUILD": 0 17 | }, 18 | "KSP_VERSION_MIN": 19 | { 20 | "MAJOR": 1, 21 | "MINOR": 8, 22 | "PATCH": 0, 23 | "BUILD": 0 24 | }, 25 | "KSP_VERSION_MAX": 26 | { 27 | "MAJOR": 1, 28 | "MINOR": 10, 29 | "PATCH": 99, 30 | "BUILD": 0 31 | }, 32 | "DOWNLOAD": "https://github.com/KSP-RO/TestFlight/releases/download/2.0.0/TestFlight-2.0.0.zip" 33 | } 34 | -------------------------------------------------------------------------------- /KSP_VERSION: -------------------------------------------------------------------------------- 1 | 1.10.1 -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestFlight")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestFlight")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("79f16ae9-c62d-4317-8d5b-9f090c15a6c4")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("2.1.0.0")] 36 | [assembly: AssemblyFileVersion("2.2.0.0")] 37 | 38 | [assembly: KSPAssembly("TestFlight", 2, 1)] 39 | [assembly: KSPAssemblyDependency("TestFlightAPI", 2, 1)] 40 | 41 | -------------------------------------------------------------------------------- /RELEASE_NOTES_RAW.txt: -------------------------------------------------------------------------------- 1 | 1.12.0.0 2 | =========== 3 | KSP Version v1.8.1 4 | 5 | 1.11.0.0 6 | =========== 7 | KSP Version v1.7.3 8 | 9 | 1.10.0.0 10 | =========== 11 | KSP Version v1.6.1 12 | 13 | Changes 14 | ----------- 15 | * Build for KSP 1.6.1 16 | 17 | 1.9.1.0 18 | =========== 19 | KSP Version v1.3.1 20 | 21 | Changes 22 | ----------- 23 | * Added ignition reliability to middle click info panel 24 | * Fixed Current Reliability values in the middle click info panel 25 | * Reworked how TF shows data in the part modules window. It now combines info from all modules into one and shows that in the same section. 26 | * Added option to disable dynamic-pressure-based ignition chance penalties 27 | * Made RandomGenerator static so that it wouldn't get reinitialized on each scene change 28 | * Disabled prelaunch ignition failures & dyn pressure penalties for any other diff preset other than Hard 29 | 30 | 1.9.0.0 31 | =========== 32 | KSP Version v1.3.1 33 | 34 | Changes 35 | ----------- 36 | * Added the ability to toggle Pre-Launch Ignition failure 37 | 38 | 39 | 1.5.4.4 40 | ===== 41 | 42 | KSP Version 43 | ----------- 44 | KSP v1.0.5 45 | 46 | Changes 47 | ------- 48 | * **FIX**: Fix R&D teams eating up insane amount of funds due to no research having been active for very long times 49 | 50 | 1.5.4.3 51 | ===== 52 | 53 | KSP Version 54 | ----------- 55 | KSP v1.0.5 56 | 57 | Changes 58 | ------- 59 | * **FIX**: Fixed PluginDir not being created on fresh installs which would prevent any settings from being saved 60 | 61 | 1.5.4.2 62 | ======= 63 | 64 | KSP Version 65 | ----------- 66 | KSP 1.0.5 67 | 68 | Changes 69 | ------- 70 | * **FIX**: Fix major bug in FloatCurve handling that was causing TestFlightFailure_IgnitionFail and TestFlightReliability_EngineCycle to both not apply proper failure chances 71 | -------------------------------------------------------------------------------- /Reliability Modules/TestFlightReliability_DynamicPressure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightReliability_DynamicPressure : TestFlightReliabilityBase 11 | { 12 | [KSPField] 13 | public FloatCurve reliabilityAtPressure = new FloatCurve(); 14 | 15 | private double oldPenalty = TestFlightUtil.MIN_FAILURE_RATE; 16 | 17 | public override void OnUpdate() 18 | { 19 | if (!TestFlightEnabled) 20 | return; 21 | 22 | if (core == null) 23 | return; 24 | 25 | double newPenalty = reliabilityAtPressure.Evaluate((float)base.vessel.dynamicPressurekPa * 1000); 26 | newPenalty = Math.Min(newPenalty, TestFlightUtil.MIN_FAILURE_RATE); 27 | 28 | if (newPenalty != oldPenalty) 29 | core.SetTriggerMomentaryFailureModifier("DynamicPressure", newPenalty, this); 30 | oldPenalty = newPenalty; 31 | } 32 | 33 | public override double GetBaseFailureRate(float flightData) 34 | { 35 | return 0; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Reliability Modules/TestFlightReliability_InternalTemperature.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightReliability_InternalTemperature : TestFlightReliabilityBase 11 | { 12 | [KSPField] 13 | public FloatCurve temperatureCurve = new FloatCurve(); 14 | 15 | private double oldPenalty = TestFlightUtil.MIN_FAILURE_RATE; 16 | 17 | public override void OnUpdate() 18 | { 19 | if (!TestFlightEnabled) 20 | return; 21 | 22 | if (core == null) 23 | return; 24 | 25 | double newPenalty = temperatureCurve.Evaluate((float)base.part.temperature); 26 | newPenalty = Math.Min(newPenalty, TestFlightUtil.MIN_FAILURE_RATE); 27 | 28 | if (newPenalty != oldPenalty) 29 | core.SetTriggerMomentaryFailureModifier("InternalTemperature", newPenalty, this); 30 | oldPenalty = newPenalty; 31 | } 32 | 33 | public override double GetBaseFailureRate(float flightData) 34 | { 35 | return 0; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Reliability Modules/TestFlightReliability_SkinTemperature.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightReliability_SkinTemperature : TestFlightReliabilityBase 11 | { 12 | [KSPField] 13 | public FloatCurve temperatureCurve = new FloatCurve(); 14 | 15 | private double oldPenalty = TestFlightUtil.MIN_FAILURE_RATE; 16 | 17 | public override void OnUpdate() 18 | { 19 | if (!TestFlightEnabled) 20 | return; 21 | 22 | if (core == null) 23 | return; 24 | 25 | double newPenalty = temperatureCurve.Evaluate((float)base.part.skinTemperature); 26 | newPenalty = Math.Min(newPenalty, TestFlightUtil.MIN_FAILURE_RATE); 27 | 28 | if (newPenalty != oldPenalty) 29 | core.SetTriggerMomentaryFailureModifier("SkinTemperature", newPenalty, this); 30 | oldPenalty = newPenalty; 31 | } 32 | 33 | public override double GetBaseFailureRate(float flightData) 34 | { 35 | return 0; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TestFlight.netkan: -------------------------------------------------------------------------------- 1 | { 2 | "spec_version" : "v1.2", 3 | "name" : "TestFlight", 4 | "abstract" : "Flight Testing of your space hardware in KSP! Fly your parts to gain flight data and make them more reliable and less likely to fail. THIS IS THE PLUGIN ONLY. You will need a TestFlight Config pack in order for any parts to actually be controlled by TestFlight. If using Realism Overhaul, the configs will be supplied by RO.", 5 | "identifier" : "TestFlight", 6 | "author" : "RP-0 Group", 7 | "$vref" : "#/ckan/ksp-avc", 8 | "$kref" : "#/ckan/github/KSP-RO/TestFlight/asset_match/TestFlightCore*", 9 | "license" : "CC-BY-NC-SA-4.0", 10 | "release_status" : "stable", 11 | "resources" : { 12 | "homepage" : "https://forum.kerbalspaceprogram.com/index.php?/topic/99043-122-testflight-v180-01-may-2017-bring-flight-testing-to-ksp/&tab=comments#comment-1705959", 13 | "repository" : "https://github.com/KSP-RO/TestFlight", 14 | "bugtracker" : "https://github.com/KSP-RO/TestFlight/issues" 15 | }, 16 | "install" : [ 17 | { 18 | "file" : "GameData/TestFlight", 19 | "install_to" : "GameData" 20 | } 21 | ], 22 | "depends" : [ 23 | { "name" : "ModuleManager", "min_version" : "2.8.0" } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /TestFlight.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlight", "TestFlight.csproj", "{411F2FC2-8E31-4FDB-9F69-E202E7B4081A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlightCore", "TestFlightCore\TestFlightCore\TestFlightCore.csproj", "{CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlightAPI", "TestFlightAPI\TestFlightAPI\TestFlightAPI.csproj", "{F212E235-8856-4C7E-AFA9-051490E1350F}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlightContracts", "TestFlightContracts\TestFlightContracts.csproj", "{2FC310C3-6160-4334-831F-573F0D5D98E2}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {2FC310C3-6160-4334-831F-573F0D5D98E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {2FC310C3-6160-4334-831F-573F0D5D98E2}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {2FC310C3-6160-4334-831F-573F0D5D98E2}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {2FC310C3-6160-4334-831F-573F0D5D98E2}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(MonoDevelopProperties) = preSolution 38 | Policies = $0 39 | $0.DotNetNamingPolicy = $1 40 | $1.DirectoryNamespaceAssociation = None 41 | $1.ResourceNamePolicy = FileFormatDefault 42 | $0.TextStylePolicy = $2 43 | $2.inheritsSet = VisualStudio 44 | $2.inheritsScope = text/plain 45 | $2.scope = text/x-csharp 46 | $0.CSharpFormattingPolicy = $3 47 | $3.IndentSwitchBody = True 48 | $3.IndentBlocksInsideExpressions = True 49 | $3.AnonymousMethodBraceStyle = NextLine 50 | $3.PropertyBraceStyle = NextLine 51 | $3.PropertyGetBraceStyle = NextLine 52 | $3.PropertySetBraceStyle = NextLine 53 | $3.EventBraceStyle = NextLine 54 | $3.EventAddBraceStyle = NextLine 55 | $3.EventRemoveBraceStyle = NextLine 56 | $3.StatementBraceStyle = NextLine 57 | $3.ElseNewLinePlacement = NewLine 58 | $3.CatchNewLinePlacement = NewLine 59 | $3.FinallyNewLinePlacement = NewLine 60 | $3.WhileNewLinePlacement = DoNotCare 61 | $3.ArrayInitializerWrapping = DoNotChange 62 | $3.ArrayInitializerBraceStyle = NextLine 63 | $3.BeforeMethodDeclarationParentheses = False 64 | $3.BeforeMethodCallParentheses = False 65 | $3.BeforeConstructorDeclarationParentheses = False 66 | $3.NewLineBeforeConstructorInitializerColon = NewLine 67 | $3.NewLineAfterConstructorInitializerColon = SameLine 68 | $3.BeforeDelegateDeclarationParentheses = False 69 | $3.NewParentheses = False 70 | $3.SpacesBeforeBrackets = False 71 | $3.inheritsSet = Mono 72 | $3.inheritsScope = text/x-csharp 73 | $3.scope = text/x-csharp 74 | $0.TextStylePolicy = $4 75 | $4.inheritsSet = VisualStudio 76 | $4.inheritsScope = text/plain 77 | $4.scope = text/plain 78 | $0.VersionControlPolicy = $5 79 | $5.inheritsSet = Mono 80 | version = 0.4.0 81 | EndGlobalSection 82 | GlobalSection(SolutionProperties) = preSolution 83 | HideSolutionNode = FALSE 84 | EndGlobalSection 85 | EndGlobal 86 | -------------------------------------------------------------------------------- /TestFlight.userprefs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /TestFlightAPI/TestFlightAPI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlightAPI", "TestFlightAPI\TestFlightAPI.csproj", "{F212E235-8856-4C7E-AFA9-051490E1350F}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | StartupItem = TestFlightAPI\TestFlightAPI.csproj 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /TestFlightAPI/TestFlightAPI.userprefs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /TestFlightAPI/TestFlightAPI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("TestFlightAPI")] 8 | [assembly: AssemblyDescription ("")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("")] 11 | [assembly: AssemblyProduct ("")] 12 | [assembly: AssemblyCopyright ("john")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("2.1.0.0")] 21 | [assembly: AssemblyFileVersion("2.2.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | 29 | [assembly: KSPAssembly("TestFlightAPI", 2, 1)] 30 | 31 | -------------------------------------------------------------------------------- /TestFlightAPI/TestFlightAPI/TestFlightAPI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {F212E235-8856-4C7E-AFA9-051490E1350F} 7 | Library 8 | TestFlightAPI 9 | TestFlightAPI 10 | v4.7.2 11 | 0.4.0 12 | 13 | 6 14 | 15 | 16 | True 17 | portable 18 | False 19 | bin\Debug 20 | DEBUG; 21 | prompt 22 | 4 23 | False 24 | 25 | 26 | false 27 | x64 28 | 29 | 30 | none 31 | True 32 | bin\Release 33 | prompt 34 | 4 35 | False 36 | 37 | 38 | false 39 | x64 40 | 41 | 42 | 43 | 44 | False 45 | 46 | 47 | False 48 | 49 | 50 | False 51 | 52 | 53 | False 54 | 55 | 56 | False 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 | -------------------------------------------------------------------------------- /TestFlightAPI/TestFlightAPI/TestFlightAPI_WIN.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {F212E235-8856-4C7E-AFA9-051490E1350F} 7 | Library 8 | TestFlightAPI 9 | TestFlightAPI 10 | v3.5 11 | 12 | 13 | True 14 | full 15 | False 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | False 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | none 29 | True 30 | bin\Release 31 | prompt 32 | 4 33 | False 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ..\..\..\..\..\KSP.app\Contents\Data\Managed\Assembly-CSharp-firstpass.dll 43 | 44 | 45 | 46 | ..\..\..\..\..\KSP.app\Contents\Data\Managed\Assembly-CSharp.dll 47 | 48 | 49 | ..\..\..\..\..\KSP.app\Contents\Data\Managed\UnityEngine.dll 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | xcopy /E /Y "$(SolutionDir)TestFlight\*.*" "F:\Games\Kerbal Space Program\0.90\GameData\TestFlight\" 74 | 75 | 76 | copy "$(TargetPath)" "F:\Games\Kerbal Space Program\0.90\GameData\TestFlight\Plugins\$(TargetFileName)" 77 | 78 | -------------------------------------------------------------------------------- /TestFlightAPI/TestFlightAPI/TestFlightPartData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace TestFlightAPI 5 | { 6 | public class TestFlightPartData : IConfigNode 7 | { 8 | [Persistent] public string partName; 9 | [Persistent] public float flightData; 10 | [Persistent] public float transferData; 11 | [Persistent] public float researchData; 12 | [Persistent] public float flightTime; 13 | private readonly Dictionary partData = new Dictionary(); 14 | 15 | public string PartName 16 | { 17 | get { return partName; } 18 | set { partName = value; } 19 | } 20 | 21 | public TestFlightPartData() 22 | { 23 | } 24 | 25 | public string GetValue(string key) 26 | { 27 | string res; 28 | return partData.TryGetValue(key.ToLowerInvariant(), out res) ? res : string.Empty; 29 | } 30 | 31 | public double GetDouble(string key) 32 | { 33 | string res = GetValue(key); 34 | double returnValue = 0; 35 | if (!string.IsNullOrEmpty(res)) 36 | double.TryParse(res, out returnValue); 37 | return returnValue; 38 | } 39 | 40 | public float GetFloat(string key) 41 | { 42 | string res = GetValue(key); 43 | float returnValue = 0; 44 | if (!string.IsNullOrEmpty(res)) 45 | float.TryParse(res, out returnValue); 46 | return returnValue; 47 | } 48 | 49 | public bool GetBool(string key) 50 | { 51 | string res = GetValue(key); 52 | bool returnValue = false; 53 | if (!string.IsNullOrEmpty(res)) 54 | bool.TryParse(res, out returnValue); 55 | return returnValue; 56 | } 57 | 58 | public int GetInt(string key) 59 | { 60 | string res = GetValue(key); 61 | int returnValue = 0; 62 | if (!string.IsNullOrEmpty(res)) 63 | int.TryParse(res, out returnValue); 64 | return returnValue; 65 | } 66 | 67 | public void SetValue(string key, object value) 68 | { 69 | key = key.ToLowerInvariant(); 70 | partData[key] = value.ToString(); 71 | } 72 | 73 | public void AddValue(string key, float value) 74 | { 75 | float existingValue = GetFloat(key); 76 | SetValue(key, existingValue + value); 77 | } 78 | 79 | public void AddValue(string key, int value) 80 | { 81 | int existingValue = GetInt(key); 82 | SetValue(key, existingValue + value); 83 | } 84 | 85 | public void ToggleValue(string key, bool _=false) 86 | { 87 | bool existingValue = GetBool(key); 88 | SetValue(key, !existingValue); 89 | } 90 | 91 | public void AddValue(string key, double value) 92 | { 93 | double existingValue = GetDouble(key); 94 | SetValue(key, existingValue + value); 95 | } 96 | 97 | private void DecodeRawPartData(string data) 98 | { 99 | var colonSep = new char[1] { ':' }; 100 | string[] propertyGroups = data.Split(new char[1]{ ',' }, StringSplitOptions.RemoveEmptyEntries); 101 | foreach (string propertyGroup in propertyGroups) 102 | { 103 | ExtractRawDataToKnownFields(propertyGroup.Split(colonSep)); 104 | } 105 | } 106 | 107 | private string EncodeRawPartData(Dictionary data) 108 | { 109 | var sb = StringBuilderCache.Acquire(); 110 | foreach (var entry in data) 111 | sb.Append($"{entry.Key}:{entry.Value},"); 112 | return sb.ToStringAndRelease(); 113 | } 114 | 115 | public void Load(ConfigNode node) 116 | { 117 | partData.Clear(); 118 | string rawPartdata = node.GetValue("partData"); 119 | ConfigNode.LoadObjectFromConfig(this, node); 120 | DecodeRawPartData(rawPartdata); 121 | } 122 | 123 | public void Save(ConfigNode node) 124 | { 125 | var tempData = new Dictionary(partData); 126 | tempData.Add(nameof(flightData).ToLowerInvariant(), $"{flightData}"); 127 | tempData.Add(nameof(transferData).ToLowerInvariant(), $"{transferData}"); 128 | tempData.Add(nameof(researchData).ToLowerInvariant(), $"{researchData}"); 129 | tempData.Add(nameof(flightTime).ToLowerInvariant(), $"{flightTime}"); 130 | node.AddValue("partData", EncodeRawPartData(tempData)); 131 | var n = ConfigNode.CreateConfigFromObject(this); 132 | node.AddData(n); 133 | } 134 | 135 | private void ExtractRawDataToKnownFields(string[] kvp) 136 | { 137 | if (kvp[0].Equals(nameof(flightData), StringComparison.OrdinalIgnoreCase)) 138 | flightData = float.Parse(kvp[1]); 139 | else if (kvp[0].Equals(nameof(researchData), StringComparison.OrdinalIgnoreCase)) 140 | researchData = float.Parse(kvp[1]); 141 | else if (kvp[0].Equals(nameof(transferData), StringComparison.OrdinalIgnoreCase)) 142 | transferData = float.Parse(kvp[1]); 143 | else if (kvp[0].Equals(nameof(flightTime), StringComparison.OrdinalIgnoreCase)) 144 | flightTime = float.Parse(kvp[1]); 145 | else 146 | SetValue(kvp[0], kvp[1]); 147 | } 148 | } 149 | } -------------------------------------------------------------------------------- /TestFlightAPI/TestFlightAPI/custom.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestFlightConfigStock.netkan: -------------------------------------------------------------------------------- 1 | { 2 | "spec_version" : "v1.2", 3 | "name" : "TestFlight Config Realism Overhaul", 4 | "abstract" : "Config pack for the TestFlight plugin. This config pack adds TestFlight support for Stock parts.", 5 | "identifier" : "TestFlightConfigStock", 6 | "$vref" : "#/ckan/ksp-avc", 7 | "$kref" : "#/ckan/github/jwvanderbeck/TestFlight/asset_match/TestFlightConfigRO*", 8 | "license" : "CC-BY-NC-SA-4.0", 9 | "release_status" : "stable", 10 | "resources" : { 11 | "homepage" : "http://forum.kerbalspaceprogram.com/threads/88187", 12 | "repository" : "https://github.com/jwvanderbeck/TestFlight", 13 | "bugtracker" : "https://github.com/jwvanderbeck/TestFlight/issues" 14 | }, 15 | "install" : [ 16 | { 17 | "file" : "GameData/TestFlight", 18 | "install_to" : "GameData" 19 | } 20 | ], 21 | "depends" : [ 22 | { "name" : "ModuleManager", "min_version" : "2.6.1" }, 23 | { "name" : "TestFlight", "min_version" : "1.3.0" } 24 | ], 25 | "provides" : [ 26 | "TestFlightConfig" 27 | ], 28 | "conflicts" : [ 29 | { "name" : "TestFlightConfig" } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /TestFlightContracts/MyClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TestFlightContracts 4 | { 5 | public class MyClass 6 | { 7 | public MyClass() 8 | { 9 | } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /TestFlightContracts/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("TestFlightContracts")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("john")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("2.1.0.0")] 21 | [assembly: AssemblyFileVersion("2.2.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | 29 | 30 | [assembly: KSPAssemblyDependency("TestFlightAPI", 2, 1)] 31 | [assembly: KSPAssemblyDependency("ContractConfigurator", 1, 0)] 32 | -------------------------------------------------------------------------------- /TestFlightContracts/TestFlightContracts.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {2FC310C3-6160-4334-831F-573F0D5D98E2} 7 | Library 8 | TestFlightContracts 9 | TestFlightContracts 10 | v4.7.2 11 | 0.4.0 12 | 13 | 6 14 | 15 | 16 | true 17 | portable 18 | false 19 | bin\Debug 20 | DEBUG; 21 | prompt 22 | 4 23 | false 24 | false 25 | x64 26 | 27 | 28 | full 29 | true 30 | bin\Release 31 | prompt 32 | 4 33 | false 34 | false 35 | x64 36 | 37 | 38 | 39 | 40 | False 41 | 42 | 43 | False 44 | 45 | 46 | False 47 | 48 | 49 | False 50 | 51 | 52 | False 53 | 54 | 55 | False 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | {F212E235-8856-4C7E-AFA9-051490E1350F} 65 | TestFlightAPI 66 | False 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /TestFlightContracts/custom.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlightCore", "TestFlightCore\TestFlightCore.csproj", "{CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | StartupItem = TestFlightCore\TestFlightCore.csproj 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore.userprefs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/BodySettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using KSP; 5 | using UnityEngine; 6 | using TestFlightCore.KSPPluginFramework; 7 | 8 | namespace TestFlightCore 9 | { 10 | public class BodySettings : ConfigNodeStorage 11 | { 12 | public BodySettings(String FilePath) : base(FilePath) { 13 | 14 | } 15 | 16 | [Persistent] public Dictionary bodyAliases = new Dictionary(); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/Framework/ExtensionsUnity.cs: -------------------------------------------------------------------------------- 1 | /* Part of KSPPluginFramework 2 | Version 1.2 3 | 4 | Forum Thread:http://forum.kerbalspaceprogram.com/threads/66503-KSP-Plugin-Framework 5 | Author: TriggerAu, 2014 6 | License: The MIT License (MIT) 7 | */ 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Text; 12 | 13 | using KSP; 14 | using UnityEngine; 15 | 16 | namespace TestFlightCore.KSPPluginFramework 17 | { 18 | /// 19 | /// CLass containing some extension methods for Unity Objects 20 | /// 21 | public static class UnityExtensions 22 | { 23 | /// 24 | /// Ensure that the Rect remains within the screen bounds 25 | /// 26 | public static Rect ClampToScreen(this Rect r) 27 | { 28 | return r.ClampToScreen(new RectOffset(0, 0, 0, 0)); 29 | } 30 | 31 | /// 32 | /// Ensure that the Rect remains within the screen bounds 33 | /// 34 | /// A Border to the screen bounds that the Rect will be clamped inside (can be negative) 35 | public static Rect ClampToScreen(this Rect r, RectOffset ScreenBorder) 36 | { 37 | r.x = Mathf.Clamp(r.x, ScreenBorder.left, Screen.width - r.width - ScreenBorder.right); 38 | r.y = Mathf.Clamp(r.y, ScreenBorder.top, Screen.height - r.height - ScreenBorder.bottom); 39 | return r; 40 | } 41 | 42 | public static GUIStyle PaddingChange(this GUIStyle g, Int32 PaddingValue) 43 | { 44 | GUIStyle gReturn = new GUIStyle(g); 45 | gReturn.padding = new RectOffset(PaddingValue, PaddingValue, PaddingValue, PaddingValue); 46 | return gReturn; 47 | } 48 | public static GUIStyle PaddingChangeBottom(this GUIStyle g, Int32 PaddingValue) 49 | { 50 | GUIStyle gReturn = new GUIStyle(g); 51 | gReturn.padding.bottom = PaddingValue; 52 | return gReturn; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/FrameworkExt/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace TestFlightCore.KSPPluginFramework 8 | { 9 | public static class EnumExtensions 10 | { 11 | public static String Description(this Enum e) 12 | { 13 | DescriptionAttribute[] desc = (DescriptionAttribute[])e.GetType().GetMember(e.ToString())[0].GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false); 14 | if (desc.Length > 0) 15 | return desc[0].Description; 16 | else 17 | return e.ToString(); 18 | } 19 | 20 | //public static List> ToEnumDescriptionsList(TEnum value) 21 | //{ 22 | // return Enum 23 | // .GetValues(typeof(TEnum)) 24 | // .Cast() 25 | // .Select(x => new KeyValuePair(x, ((Enum)((object)x)).Description())) 26 | // .ToList(); 27 | //} 28 | //public static List> ToEnumDescriptionsList() 29 | //{ 30 | // return ToEnumDescriptionsList(default(TEnum)); 31 | //} 32 | 33 | //limit it to accept enums only 34 | public static List ToEnumDescriptions(TEnum value) where TEnum : struct,IConvertible 35 | { 36 | List> temp = Enum 37 | .GetValues(typeof(TEnum)) 38 | .Cast() 39 | .Select(x => new KeyValuePair(x, ((Enum)((System.Object)x)).Description())) 40 | .ToList(); 41 | return temp.Select(x => x.Value).ToList(); 42 | } 43 | public static List ToEnumDescriptions() where TEnum : struct,IConvertible 44 | { 45 | return ToEnumDescriptions(default(TEnum)).ToList(); 46 | } 47 | 48 | 49 | 50 | public static T Clamp(this T val, T min, T max) where T : IComparable 51 | { 52 | if (val.CompareTo(min) < 0) return min; 53 | else if (val.CompareTo(max) > 0) return max; 54 | else return val; 55 | } 56 | 57 | public static Int32 ToInt32(this String s) 58 | { 59 | return Convert.ToInt32(s); 60 | } 61 | 62 | public static Int32 NormalizeAngle360(this Int32 val) { 63 | return (Int32)Convert.ToDouble(val).NormalizeAngle360(); 64 | } 65 | 66 | public static Double NormalizeAngle360(this Double val) 67 | { 68 | val %= 360; 69 | if (val < 0) 70 | val += 360; 71 | return val; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("TestFlightCore")] 8 | [assembly: AssemblyDescription ("")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("")] 11 | [assembly: AssemblyProduct ("")] 12 | [assembly: AssemblyCopyright ("john")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("2.1.0.0")] 21 | [assembly: AssemblyFileVersion("2.2.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | 29 | [assembly: KSPAssemblyDependency("TestFlightAPI", 2, 1)] 30 | 31 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/TestFlightCore_WIN.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2} 7 | Library 8 | TestFlightCore 9 | TestFlightCore 10 | v3.5 11 | 12 | 13 | False 14 | bin\Debug 15 | DEBUG; 16 | prompt 17 | 4 18 | False 19 | 20 | 21 | 22 | 23 | 24 | 25 | none 26 | 27 | 28 | none 29 | True 30 | bin\Release 31 | prompt 32 | 4 33 | False 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ..\..\..\..\..\KSP.app\Contents\Data\Managed\Assembly-CSharp.dll 45 | 46 | 47 | ..\..\..\..\..\KSP.app\Contents\Data\Managed\UnityEngine.dll 48 | 49 | 50 | ..\..\..\..\..\KSP.app\Contents\Data\Managed\Assembly-CSharp-firstpass.dll 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 | {F212E235-8856-4C7E-AFA9-051490E1350F} 85 | TestFlightAPI 86 | 87 | 88 | 89 | copy "$(TargetPath)" "F:\Games\Kerbal Space Program\0.90\GameData\TestFlight\Plugins\$(TargetFileName)" 90 | 91 | 92 | xcopy /E /Y "$(SolutionDir)TestFlight\*.*" "F:\Games\Kerbal Space Program\0.90\GameData\TestFlight\" 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/TestFlightRnD.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using UnityEngine; 7 | using KSP.UI.Screens; 8 | using TestFlightAPI; 9 | 10 | namespace TestFlightCore 11 | { 12 | [KSPAddon(KSPAddon.Startup.SpaceCentre, true)] 13 | public class TestFlightRnD : MonoBehaviour 14 | { 15 | Dictionary baseCost = null; 16 | 17 | public void Start() 18 | { 19 | RDController.OnRDTreeSpawn.Add(OnTreeSpawn); 20 | DontDestroyOnLoad(this); 21 | } 22 | 23 | public void OnTreeSpawn(RDController controller) 24 | { 25 | if (TestFlightManagerScenario.Instance == null || controller.nodes == null || 26 | !TestFlightManagerScenario.Instance.SettingsTechDiscountEnabled) 27 | { 28 | return; 29 | } 30 | List nodes = controller.nodes; 31 | if (this.baseCost == null) 32 | { 33 | baseCost = new Dictionary(); 34 | for (int i = 0; i < nodes.Count; i++) 35 | { 36 | RDNode node = nodes[i]; 37 | if (node != null && node.tech != null) 38 | { 39 | baseCost.Add(nodes[i].tech.techID, nodes[i].tech.scienceCost); 40 | } 41 | } 42 | } 43 | for (int n = 0; n < nodes.Count; n++) 44 | { 45 | RDNode node = nodes[n]; 46 | if (node != null && node.tech != null && !node.IsResearched && node.tech.partsAssigned != null) 47 | { 48 | float discount = 0f; 49 | List parts = node.tech.partsAssigned; 50 | for (int p = 0; p < parts.Count; p++) 51 | { 52 | if (parts[p] != null) 53 | { 54 | Part prefab = parts[p].partPrefab; 55 | TestFlightPartData partData = TestFlightManagerScenario.Instance.GetPartDataForPart(parts[p].name); 56 | if (partData != null && prefab != null) 57 | { 58 | TestFlightCore core = (TestFlightCore)prefab.Modules.OfType().FirstOrDefault(); 59 | float flightData = partData.flightData; 60 | if (core != null && flightData > core.startFlightData) 61 | { 62 | discount += (int)(((flightData - core.startFlightData) / (core.maxData - core.startFlightData)) * core.scienceDataValue); 63 | } 64 | } 65 | } 66 | } 67 | if (discount > 0) 68 | { 69 | node.tech.scienceCost = (int)Math.Max(0, baseCost[node.tech.techID] - discount); 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/UserInterface.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Mono Runtime Version: 4.0.30319.1 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | // ------------------------------------------------------------------------------ 10 | using System; 11 | using KSP; 12 | using UnityEngine; 13 | using TestFlightCore.KSPPluginFramework; 14 | 15 | namespace TestFlightCore 16 | { 17 | internal static class OldStyles 18 | { 19 | internal static GUIStyle panelStyle; 20 | 21 | internal static GUIStyle textStyleCritical; 22 | internal static GUIStyle textStyleWarning; 23 | internal static GUIStyle textStyleSafe; 24 | internal static GUIStyle textStyleStandard; 25 | 26 | internal static GUIStyle stylePanel; 27 | internal static GUIStyle styleButton; 28 | internal static GUIStyle styleButtonUnity; 29 | internal static GUIStyle styleButtonMain; 30 | internal static GUIStyle styleButtonMainUnity; 31 | internal static GUIStyle styleButtonSettings; 32 | 33 | 34 | internal static void Init() 35 | { 36 | panelStyle = new GUIStyle(SkinsLibrary.DefKSPSkin.window); 37 | // panelStyle.border = new RectOffset(6, 6, 6, 6); 38 | // panelStyle.padding = new RectOffset(8, 3, 7, 0); 39 | 40 | stylePanel = new GUIStyle(); 41 | stylePanel.normal.background = TestFlight.Resources.texPanel; 42 | stylePanel.border = new RectOffset(6, 6, 6, 6); 43 | stylePanel.padding = new RectOffset(8, 3, 7, 0); 44 | 45 | textStyleStandard = new GUIStyle(SkinsLibrary.DefUnitySkin.label); 46 | textStyleStandard.fontSize = 12; 47 | textStyleStandard.alignment = TextAnchor.MiddleLeft; 48 | textStyleStandard.normal.textColor = new Color(253, 246, 227); 49 | textStyleStandard.wordWrap = false; 50 | 51 | textStyleSafe = new GUIStyle(textStyleStandard); 52 | textStyleSafe.normal.textColor = new Color32(133, 153, 0, 255); 53 | 54 | textStyleWarning = new GUIStyle(textStyleStandard); 55 | textStyleWarning.normal.textColor = new Color32(203, 75, 22, 255); 56 | 57 | textStyleCritical = new GUIStyle(textStyleStandard); 58 | textStyleCritical.normal.textColor = new Color32(220, 50, 47, 255); 59 | 60 | styleButton = new GUIStyle(SkinsLibrary.DefUnitySkin.button); 61 | styleButton.name = "ButtonGeneral"; 62 | styleButton.normal.background = SkinsLibrary.DefKSPSkin.button.normal.background; 63 | styleButton.hover.background = SkinsLibrary.DefKSPSkin.button.hover.background; 64 | styleButton.normal.textColor = new Color(207, 207, 207); 65 | styleButton.fontStyle = FontStyle.Normal; 66 | styleButton.fixedHeight = 20; 67 | styleButton.padding.top = 2; 68 | 69 | styleButtonUnity = new GUIStyle(styleButton); 70 | styleButtonUnity.normal.background = SkinsLibrary.DefUnitySkin.button.normal.background; 71 | styleButtonUnity.hover.background = SkinsLibrary.DefUnitySkin.button.hover.background; 72 | 73 | styleButtonMain = new GUIStyle(styleButton); 74 | styleButtonMain.name = "ButtonMain"; 75 | styleButtonMain.fixedHeight = 20; 76 | 77 | styleButtonMainUnity = new GUIStyle(styleButtonMain); 78 | styleButtonMainUnity.normal.background = SkinsLibrary.DefUnitySkin.button.normal.background; 79 | styleButtonMainUnity.hover.background = SkinsLibrary.DefUnitySkin.button.hover.background; 80 | 81 | 82 | styleButtonSettings = new GUIStyle(styleButton); 83 | styleButtonSettings.name = "ButtonSettings"; 84 | styleButtonSettings.padding = new RectOffset(1, 1, 1, 1); 85 | 86 | 87 | //Default Skin 88 | // GUISkin DefKSP = SkinsLibrary.CopySkin(SkinsLibrary.DefSkinType.KSP); 89 | // DefKSP.window = stylePanel; 90 | // DefKSP.font = SkinsLibrary.DefUnitySkin.font; 91 | // DefKSP.horizontalSlider.margin.top = 8; 92 | // SkinsLibrary.AddSkin("Default", DefKSP); 93 | // 94 | // //Adjust Default Skins 95 | // SkinsLibrary.List["Default"].button = new GUIStyle(styleButton); 96 | // SkinsLibrary.List["Default"].label = new GUIStyle(styleText); 97 | // 98 | // //Add Styles once skin is added 99 | // SkinsLibrary.AddStyle("Default", styleTooltipStyle); 100 | // SkinsLibrary.AddStyle("Default", styleButton); 101 | // SkinsLibrary.AddStyle("Default", styleButtonMain); 102 | // SkinsLibrary.AddStyle("Default", styleButtonSettings); 103 | // SkinsLibrary.AddStyle("Default", "DropDownButton", styleDropDownButton); 104 | // SkinsLibrary.AddStyle("Default", "DropDownListBox", styleDropDownListBox); 105 | // SkinsLibrary.AddStyle("Default", "DropDownListItem", styleDropDownListItem); 106 | } 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /TestFlightCore/TestFlightCore/custom.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestFlightFailure_EnginePerformanceLoss.cs: -------------------------------------------------------------------------------- 1 | namespace TestFlight 2 | { 3 | public class TestFlightFailure_EnginePerformanceLoss : TestFlightFailure_Engine 4 | { 5 | [KSPField] 6 | public float ispMultiplier = 0.7f; 7 | [KSPField] 8 | public float ispMultiplierJitter = 0.1f; 9 | 10 | public override void OnStart(StartState state) 11 | { 12 | base.OnStart(state); 13 | if (Failed) 14 | DoFailure(); 15 | } 16 | /// 17 | /// Triggers the failure controlled by the failure module 18 | /// 19 | public override void DoFailure() 20 | { 21 | base.DoFailure(); 22 | // for each engine change its specific impulse 23 | foreach (EngineHandler engine in engines) 24 | { 25 | float jitter = ispMultiplierJitter - ((float)core.RandomGenerator.NextDouble() * (ispMultiplierJitter * 2)); 26 | float actualMultiplier = ispMultiplier + jitter; 27 | engine.engine.SetFuelIspMult(actualMultiplier); 28 | engine.engine.failMessage = failureTitle; 29 | engine.engine.failed = true; 30 | } 31 | } 32 | 33 | public override float DoRepair() 34 | { 35 | base.DoRepair(); 36 | // for each engine restore its specific impulse back to 1.0 37 | foreach (EngineHandler engine in engines) 38 | { 39 | engine.engine.SetFuelIspMult(1.0f); 40 | engine.engine.failMessage = ""; 41 | engine.engine.failed = false; 42 | } 43 | return 0; 44 | } 45 | public override void SetActiveConfig(string alias) 46 | { 47 | base.SetActiveConfig(alias); 48 | 49 | if (currentConfig == null) return; 50 | 51 | // update current values with those from the current config node 52 | currentConfig.TryGetValue("ispMultiplier", ref ispMultiplier); 53 | currentConfig.TryGetValue("ispMultiplierJitter", ref ispMultiplierJitter); 54 | } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /TestFlightFailure_Explode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | using UnityEngine; 7 | using TestFlightAPI; 8 | 9 | namespace TestFlight 10 | { 11 | public class TestFlightFailure_Explode : TestFlightFailureBase 12 | { 13 | /// 14 | /// Triggers the failure controlled by the failure module 15 | /// 16 | public override void DoFailure() 17 | { 18 | base.DoFailure(); 19 | this.part.explode(); 20 | } 21 | 22 | /// 23 | /// Asks the repair module if all condtions have been met for the player to attempt repair of the failure. Here the module can verify things such as the conditions (landed, eva, splashed), parts requirements, etc 24 | /// 25 | /// true if this instance can attempt repair; otherwise, false. 26 | public override bool CanAttemptRepair() 27 | { 28 | return false; 29 | } 30 | 31 | public override float DoRepair() 32 | { 33 | return -1; 34 | } 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /TestFlightFailure_LockGimbal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | using UnityEngine; 7 | using TestFlightAPI; 8 | 9 | namespace TestFlight 10 | { 11 | public class TestFlightFailure_LockGimbal : TestFlightFailureBase 12 | { 13 | /// 14 | /// Triggers the failure controlled by the failure module 15 | /// 16 | 17 | private float gimbalRange; 18 | 19 | public override void OnStart(StartState state) 20 | { 21 | base.OnStart(state); 22 | if (Failed) 23 | DoFailure(); 24 | } 25 | 26 | public override void DoFailure() 27 | { 28 | base.DoFailure(); 29 | List gimbals = this.part.Modules.OfType().ToList(); 30 | foreach (ModuleGimbal gimbal in gimbals) 31 | { 32 | gimbalRange = gimbal.gimbalRange; 33 | gimbal.gimbalRange = 0f; 34 | } 35 | } 36 | 37 | public override float DoRepair() 38 | { 39 | base.DoRepair(); 40 | List gimbals = this.part.Modules.OfType().ToList(); 41 | foreach (ModuleGimbal gimbal in gimbals) 42 | { 43 | gimbal.gimbalRange = gimbalRange; 44 | } 45 | 46 | return 0; 47 | } 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /TestFlightFailure_ReducedMaxThrust.cs: -------------------------------------------------------------------------------- 1 | namespace TestFlight 2 | { 3 | public class TestFlightFailure_ReducedMaxThrust : TestFlightFailure_Engine 4 | { 5 | [KSPField] 6 | public float thrustReduction = 0.5f; 7 | 8 | public override void OnStart(StartState state) 9 | { 10 | base.OnStart(state); 11 | if (Failed) 12 | DoFailure(); 13 | } 14 | public override void SetActiveConfig(string alias) 15 | { 16 | base.SetActiveConfig(alias); 17 | 18 | if (currentConfig == null) return; 19 | 20 | // update current values with those from the current config node 21 | currentConfig.TryGetValue("thrustReduction", ref thrustReduction); 22 | } 23 | 24 | /// 25 | /// Triggers the failure controlled by the failure module 26 | /// 27 | public override void DoFailure() 28 | { 29 | base.DoFailure(); 30 | // for each engine change its fuelFlow which will affect thrust 31 | foreach (EngineHandler engine in engines) 32 | { 33 | engine.engine.SetFuelFlowMult(thrustReduction); 34 | engine.engine.failed = true; 35 | engine.engine.failMessage = failureTitle; 36 | } 37 | } 38 | 39 | public override float DoRepair() 40 | { 41 | base.DoRepair(); 42 | // for each engine restore its fuell flow back to 1.0 43 | foreach (EngineHandler engine in engines) 44 | { 45 | engine.engine.SetFuelFlowMult(1.0f); 46 | engine.engine.failed = false; 47 | engine.engine.failMessage = ""; 48 | } 49 | return 0; 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /TestFlightFailure_ShutdownEngine.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace TestFlight 4 | { 5 | public class TestFlightFailure_ShutdownEngine : TestFlightFailure_Engine 6 | { 7 | public override void OnStart(StartState state) 8 | { 9 | base.OnStart(state); 10 | 11 | if (Failed && IsMajor) 12 | { 13 | foreach (EngineHandler engine in engines) 14 | { 15 | engine.engine.DisableRestart(); 16 | engine.engine.failed = true; 17 | engine.engine.failMessage = failureTitle; 18 | } 19 | } 20 | } 21 | 22 | /// 23 | /// Triggers the failure controlled by the failure module 24 | /// 25 | public override void DoFailure() 26 | { 27 | base.DoFailure(); 28 | if (engineStates == null) 29 | engineStates = new Dictionary(); 30 | engineStates.Clear(); 31 | foreach (EngineHandler engine in engines) 32 | { 33 | int id = engines.IndexOf(engine); 34 | var engineState = new CachedEngineState(engine.engine); 35 | engine.engine.Shutdown(); 36 | var numIgnitionsToRemove = 1; 37 | if (IsMajor) 38 | { 39 | numIgnitionsToRemove = -1; 40 | 41 | engine.engine.DisableRestart(); 42 | engine.engine.failed = true; 43 | engine.engine.failMessage = failureTitle; 44 | } 45 | engineStates.Add(id, engineState); 46 | engine.engine.RemoveIgnitions(numIgnitionsToRemove); 47 | } 48 | } 49 | 50 | public override float DoRepair() 51 | { 52 | // for each engine restore it 53 | foreach (EngineHandler engine in engines) 54 | { 55 | int id = engines.IndexOf(engine); 56 | CachedEngineState engineState = null; 57 | if (engineStates?.TryGetValue(id, out engineState) ?? false) 58 | { 59 | engine.engine.enabled = true; 60 | engine.engine.Events["Activate"].active = true; 61 | engine.engine.Events["Activate"].guiActive = true; 62 | engine.engine.Events["Shutdown"].guiActive = true; 63 | engine.engine.allowShutdown = engineState.allowShutdown; 64 | engine.engine.allowRestart = engineState.allowRestart; 65 | engine.engine.SetIgnitionCount(engineState.numIgnitions); 66 | engine.engine.failed = false; 67 | engine.engine.failMessage = ""; 68 | } 69 | } 70 | engineStates.Clear(); 71 | base.DoRepair(); 72 | return 0; 73 | } 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /TestFlightMain.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "follow_symlinks": true, 6 | "path": ".", 7 | "file_exclude_patterns": 8 | [ 9 | "*.dll", 10 | "*.meta" 11 | ] 12 | } 13 | ], 14 | "build_systems" : 15 | [ 16 | { 17 | "name" : "Build", 18 | "shell_cmd": "/Applications/Unity/MonoDevelop.app/Contents/MacOS/mdtool build ~/Developer/KSP/0.90/TestFlightDEV/Dev/_DEV/GitHub/TestFlight/TestFlight.sln", 19 | "selector" : "source.Unity3D/UnityC#", 20 | "working_dir" : "$(project_path)" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /TestFlightRF/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("TestFlightRF")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("john")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | [assembly: KSPAssemblyDependency("TestFlightAPI", 1, 5)] 29 | [assembly: KSPAssemblyDependency("TestFlight", 1, 5)] 30 | // Need RF to do this first 31 | // [assembly: KSPAssemblyDependency("RealFuels", 10, 8)] -------------------------------------------------------------------------------- /TestFlightRF/TestFlightRF.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {ACF86439-AE81-4118-B703-2BBACC483B7E} 7 | Library 8 | TestFlightRF 9 | TestFlightRF 10 | 0.4.0 11 | v3.5 12 | 13 | 14 | true 15 | full 16 | false 17 | bin\Debug 18 | DEBUG; 19 | prompt 20 | 4 21 | false 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | full 30 | true 31 | bin\Release 32 | prompt 33 | 4 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | $(KSP_DLL_PATH)\RealFuels.dll 46 | 47 | 48 | $(KSP_DLL_PATH)\Assembly-CSharp-firstpass.dll 49 | 50 | 51 | $(KSP_DLL_PATH)\Assembly-CSharp.dll 52 | 53 | 54 | $(KSP_DLL_PATH)\UnityEngine.dll 55 | 56 | 57 | $(KSP_DLL_PATH)\UnityEngine.UI.dll 58 | 59 | 60 | $(KSP_DLL_PATH)\KSPUtil.dll 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | {F212E235-8856-4C7E-AFA9-051490E1350F} 71 | TestFlightAPI 72 | 73 | 74 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A} 75 | TestFlight 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /TestFlightRF/TestFlightRF.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | CSharp50 -------------------------------------------------------------------------------- /TestFlightRF/TestFlightRealFuels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using RealFuels; 6 | using TestFlight; 7 | using TestFlightAPI; 8 | 9 | namespace TestFlightRF 10 | { 11 | [KSPAddon(KSPAddon.Startup.MainMenu, true)] 12 | public class TestFlightRealFuels : MonoBehaviour 13 | { 14 | protected Dictionary burnTimes = null; 15 | 16 | IEnumerator Setup() 17 | { 18 | if (!PartLoader.Instance.IsReady() || PartResourceLibrary.Instance == null) 19 | { 20 | yield return null; 21 | } 22 | Startup(); 23 | } 24 | 25 | public void Startup() 26 | { 27 | burnTimes = new Dictionary(); 28 | foreach (AvailablePart part in PartLoader.LoadedPartsList) 29 | { 30 | // cache up the burn times first 31 | List engineCycles = new List(); 32 | burnTimes.Clear(); 33 | foreach (PartModule pm in part.partPrefab.Modules) 34 | { 35 | ITestFlightReliability reliabilityModule = pm as ITestFlightReliability; 36 | if (reliabilityModule != null) 37 | engineCycles.Add(reliabilityModule); 38 | } 39 | if (engineCycles.Count <= 0) 40 | continue; 41 | 42 | foreach (ITestFlightReliability rm in engineCycles) 43 | { 44 | TestFlightReliability_EngineCycle engineCycle = rm as TestFlightReliability_EngineCycle; 45 | if (engineCycle != null) 46 | { 47 | if (engineCycle.engineConfig != "") 48 | { 49 | burnTimes[engineCycle.engineConfig] = engineCycle.ratedBurnTime; 50 | } 51 | } 52 | } 53 | // now add that info to the RF configs 54 | List allConfigs = new List(); 55 | allConfigs.AddRange(part.partPrefab.Modules.GetModules()); 56 | if (allConfigs.Count <= 0) 57 | continue; 58 | 59 | foreach (ModuleEngineConfigs mec in allConfigs) 60 | { 61 | List configs = mec.configs; 62 | foreach (ConfigNode node in configs) 63 | { 64 | if (node.HasValue("name")) 65 | { 66 | string configName = node.GetValue("name"); 67 | if (burnTimes.ContainsKey(configName)) 68 | { 69 | if (node.HasValue("description")) 70 | { 71 | string description = node.GetValue("description"); 72 | description += String.Format("\n" + " " + "Rated Burn Time: {0}", TestFlightUtil.FormatTime(burnTimes[configName], TestFlightUtil.TIMEFORMAT.SHORT_IDENTIFIER, true)); 73 | node.SetValue("description", description, true); 74 | } 75 | else 76 | { 77 | node.AddValue("description", String.Format("\nRated Burn Time {0}", TestFlightUtil.FormatTime(burnTimes[configName], TestFlightUtil.TIMEFORMAT.SHORT_IDENTIFIER, true))); 78 | } 79 | } 80 | } 81 | } 82 | mec.SetConfiguration(); 83 | } 84 | } 85 | } 86 | 87 | public void Start() 88 | { 89 | StartCoroutine("Setup"); 90 | } 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /TestFlightRF/custom.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TestFlightReliability.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using TestFlightAPI; 5 | using TestFlightCore; 6 | 7 | namespace TestFlight 8 | { 9 | /// 10 | /// This part module determines the part's current reliability and passes that on to the TestFlight core. 11 | /// 12 | public class TestFlightReliability : TestFlightReliabilityBase 13 | { 14 | public override string GetModuleInfo(string configuration, float reliabilityAtTime) 15 | { 16 | foreach (var configNode in configs) 17 | { 18 | if (!configNode.HasValue("configuration")) 19 | continue; 20 | 21 | var nodeConfiguration = configNode.GetValue("configuration"); 22 | 23 | if (string.Equals(nodeConfiguration, configuration, StringComparison.InvariantCultureIgnoreCase)) 24 | { 25 | if (configNode.HasNode("reliabilityCurve")) 26 | { 27 | var nodeReliability = new FloatCurve(); 28 | nodeReliability.Load(configNode.GetNode("reliabilityCurve")); 29 | 30 | // core is not yet available here 31 | float reliabilityMin = TestFlightUtil.FailureRateToReliability(nodeReliability.Evaluate(nodeReliability.minTime), reliabilityAtTime); 32 | float reliabilityMax = TestFlightUtil.FailureRateToReliability(nodeReliability.Evaluate(nodeReliability.maxTime), reliabilityAtTime); 33 | return $" Reliability at 0 data: {reliabilityMin:P1}\n Reliability at max data: {reliabilityMax:p1}"; 34 | } 35 | } 36 | } 37 | 38 | return base.GetModuleInfo(configuration, reliabilityAtTime); 39 | } 40 | 41 | public override List GetTestFlightInfo(float reliabilityAtTime) 42 | { 43 | List infoStrings = new List(); 44 | 45 | if (core == null) 46 | { 47 | Log("Core is null"); 48 | return infoStrings; 49 | } 50 | if (reliabilityCurve == null) 51 | { 52 | Log("Curve is null"); 53 | return infoStrings; 54 | } 55 | 56 | float flightData = core.GetFlightData(); 57 | if (flightData < 0f) 58 | flightData = 0f; 59 | 60 | double currentFailRate = GetBaseFailureRate(flightData); 61 | double maxFailRate = GetBaseFailureRate(reliabilityCurve.maxTime); 62 | 63 | double currentReliability = TestFlightUtil.FailureRateToReliability(currentFailRate, reliabilityAtTime); 64 | double maxReliability = TestFlightUtil.FailureRateToReliability(maxFailRate, reliabilityAtTime); 65 | 66 | string currentMTBF = core.FailureRateToMTBFString(currentFailRate, TestFlightUtil.MTBFUnits.SECONDS, 999); 67 | string maxMTBF = core.FailureRateToMTBFString(maxFailRate, TestFlightUtil.MTBFUnits.SECONDS, 999); 68 | 69 | infoStrings.Add("Base Reliability"); 70 | infoStrings.Add($"Current Reliability: {currentReliability:P1} at full burn, {currentMTBF} MTBF"); 71 | infoStrings.Add($"Maximum Reliability: {maxReliability:P1} at full burn, {maxMTBF} MTBF"); 72 | 73 | return infoStrings; 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /TestFlightReliability_TestFail.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using TestFlightAPI; 7 | 8 | namespace TestFlight 9 | { 10 | public class TestFlightReliability_TestFail : TestFlightReliabilityBase 11 | { 12 | [KSPEvent(guiName = "Force Failure", active = true, guiActive = true)] 13 | public void ForceFailure() 14 | { 15 | string message = "Part has failed after forced failure"; 16 | message = String.Format("TestFlightReliability({0}[{1}]): {2}", Configuration, Configuration, message); 17 | TestFlightUtil.Log(message, this.part); 18 | 19 | core.TriggerFailure(); 20 | } 21 | public override void OnUpdate() 22 | { 23 | base.OnUpdate(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TestFlightSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | using UnityEngine; 9 | 10 | using TestFlightAPI; 11 | 12 | namespace TestFlight 13 | { 14 | public class TestFlightGameSettings : GameParameters.CustomParameterNode 15 | { 16 | public override string Title { get { return "TestFlight Options"; } } 17 | public override GameParameters.GameMode GameMode { get { return GameParameters.GameMode.ANY; } } 18 | public override string Section { get { return "TestFlight"; } } 19 | public override string DisplaySection { get { return Section; } } 20 | public override int SectionOrder { get { return 1; } } 21 | public override bool HasPresets { get { return true; } } 22 | 23 | [GameParameters.CustomParameterUI("Pre-Launch Ignition Failures", toolTip = "Set to enable ignition failures on the Launch Pad.")] 24 | public bool preLaunchFailures = true; 25 | 26 | [GameParameters.CustomParameterUI("Ignition Chance Penalty For High Dynamic Pressure", toolTip = "Whether engine ignition chance will suffer a penalty based on dynamic pressure.")] 27 | public bool dynPressurePenalties = true; 28 | 29 | // The following values are persisted to the savegame but are not shown in the difficulty settings UI 30 | public bool dynPressurePenaltyReminderShown = false; 31 | public bool restartWindowPenaltyReminderShown = false; 32 | 33 | public override void SetDifficultyPreset(GameParameters.Preset preset) 34 | { 35 | switch (preset) 36 | { 37 | case GameParameters.Preset.Easy: 38 | case GameParameters.Preset.Normal: 39 | case GameParameters.Preset.Moderate: 40 | preLaunchFailures = false; 41 | break; 42 | case GameParameters.Preset.Hard: 43 | preLaunchFailures = true; 44 | break; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /TestFlight_WIN.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlight", "TestFlight.csproj", "{411F2FC2-8E31-4FDB-9F69-E202E7B4081A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlightCore", "TestFlightCore\TestFlightCore\TestFlightCore.csproj", "{CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestFlightAPI", "TestFlightAPI\TestFlightAPI\TestFlightAPI.csproj", "{F212E235-8856-4C7E-AFA9-051490E1350F}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {411F2FC2-8E31-4FDB-9F69-E202E7B4081A}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {CD4D0CF1-16A8-4FB9-A7CC-6566160B8CD2}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {F212E235-8856-4C7E-AFA9-051490E1350F}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(MonoDevelopProperties) = preSolution 35 | StartupItem = TestFlight.csproj 36 | Policies = $0 37 | $0.DotNetNamingPolicy = $1 38 | $1.DirectoryNamespaceAssociation = None 39 | $1.ResourceNamePolicy = FileFormatDefault 40 | $0.TextStylePolicy = $4 41 | $2.inheritsSet = VisualStudio 42 | $2.inheritsScope = text/plain 43 | $2.scope = text/x-csharp 44 | $0.CSharpFormattingPolicy = $3 45 | $3.IndentSwitchBody = True 46 | $3.IndentBlocksInsideExpressions = True 47 | $3.AnonymousMethodBraceStyle = NextLine 48 | $3.PropertyBraceStyle = NextLine 49 | $3.PropertyGetBraceStyle = NextLine 50 | $3.PropertySetBraceStyle = NextLine 51 | $3.EventBraceStyle = NextLine 52 | $3.EventAddBraceStyle = NextLine 53 | $3.EventRemoveBraceStyle = NextLine 54 | $3.StatementBraceStyle = NextLine 55 | $3.ElseNewLinePlacement = NewLine 56 | $3.CatchNewLinePlacement = NewLine 57 | $3.FinallyNewLinePlacement = NewLine 58 | $3.WhileNewLinePlacement = DoNotCare 59 | $3.ArrayInitializerWrapping = DoNotChange 60 | $3.ArrayInitializerBraceStyle = NextLine 61 | $3.BeforeMethodDeclarationParentheses = False 62 | $3.BeforeMethodCallParentheses = False 63 | $3.BeforeConstructorDeclarationParentheses = False 64 | $3.NewLineBeforeConstructorInitializerColon = NewLine 65 | $3.NewLineAfterConstructorInitializerColon = SameLine 66 | $3.BeforeDelegateDeclarationParentheses = False 67 | $3.NewParentheses = False 68 | $3.SpacesBeforeBrackets = False 69 | $3.inheritsSet = Mono 70 | $3.inheritsScope = text/x-csharp 71 | $3.scope = text/x-csharp 72 | $4.inheritsSet = VisualStudio 73 | $4.inheritsScope = text/plain 74 | $4.scope = text/plain 75 | EndGlobalSection 76 | EndGlobal 77 | -------------------------------------------------------------------------------- /buildChangelog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | import urllib, json, argparse, sys, os, codecs 3 | 4 | class DefaultHelpParser(argparse.ArgumentParser): 5 | def error(self, message): 6 | sys.stderr.write('error: %s\n' % message) 7 | self.print_help() 8 | sys.exit(2) 9 | 10 | HELP_DESC = "Auto creates change log for next version based on commits since last release or a specified tagged release" 11 | parser = DefaultHelpParser(description=HELP_DESC) 12 | parser.add_argument('version', metavar='version', type=str, nargs=1, 13 | help='version number of *next* release version in format v1.2.3.4') 14 | parser.add_argument('--tag', metavar='tag', type=str, 15 | help='Tagged release to use for building the changelog in the format 1.2.3.4') 16 | parser.add_argument('--branch', metavar='branch', type=str, 17 | help='Branch to look at for commits') 18 | 19 | args = parser.parse_args() 20 | 21 | if not args.version or len(args.version) < 1: 22 | print "ERROR: Next release version must be specified" 23 | sys.exit(2) 24 | 25 | if not args.branch: 26 | args.branch = "master" 27 | 28 | if (args.tag): 29 | releaseURL = urllib.urlopen("https://api.github.com/repos/KSP-RO/TestFlight/releases/tags/" + args.tag) 30 | else: 31 | releaseURL = urllib.urlopen("https://api.github.com/repos/KSP-RO/TestFlight/releases/latest") 32 | latestRelease = json.load(releaseURL) 33 | print latestRelease 34 | sinceDate = latestRelease["created_at"] 35 | print "Getting since date: " + sinceDate 36 | print "Using branch: " + args.branch 37 | commitsURL = urllib.urlopen("https://api.github.com/repos/KSP-RO/TestFlight/commits?since=" + sinceDate + "&sha=" + args.branch) 38 | print "https://api.github.com/repos/KSP-RO/TestFlight/commits?since=" + sinceDate + "?sha=" + args.branch 39 | commits = json.load(commitsURL) 40 | print commits 41 | 42 | commits = commits[:-1] 43 | 44 | print args.version[0] 45 | print "----------\n" 46 | for commit in commits: 47 | if not commit["commit"]["message"].startswith("-"): 48 | formattedMessage = commit["commit"]["message"].replace("\n\n", "\n").replace("\n", "").replace("NEW:", "\n* **NEW**:").replace("FIX:", "\n* **FIX**:") 49 | print formattedMessage 50 | -------------------------------------------------------------------------------- /configs/Stock/Squad_Tanks.json: -------------------------------------------------------------------------------- 1 | { 2 | "ReliabilityDefinitions" : 3 | { 4 | "HighReliability" : 5 | { 6 | "default" : 7 | [ 8 | "key = 0 0.005", 9 | "key = 1000 0.0025", 10 | "key = 10000 0.0001" 11 | ] 12 | } 13 | }, 14 | "RepairConfigs" : 15 | { 16 | "EasySoftware" : 17 | { 18 | "canBeRepairedByRemote" : true, 19 | "canBeRepairedInFlight" : true, 20 | "canBeRepairedOnSplashed" : true, 21 | "dataScale" : 1, 22 | "dataSize" : 1, 23 | "repairChance" : 75 24 | }, 25 | "MediumHydraulic" : 26 | { 27 | "canBeRepairedByRemote" : false, 28 | "canBeRepairedInFlight" : false, 29 | "canBeRepairedOnSplashed" : false, 30 | "repairChance" : 50, 31 | "replacementPart" : "HydraulicGizmo", 32 | "replacementPartOptional" : true, 33 | "replacementPartBonus" : 0.10 34 | }, 35 | "EasyMechanical" : 36 | { 37 | "canBeRepairedByRemote" : false, 38 | "canBeRepairedInFlight" : false, 39 | "canBeRepairedOnSplashed" : false, 40 | "repairChance" : 75 41 | } 42 | }, 43 | "FailureConfigs" : 44 | { 45 | "Explode" : 46 | { 47 | "failureTitle" : "Explosion!", 48 | "failureType" : "mechanical", 49 | "severity" : "major" 50 | }, 51 | "ResourceLeak_LiquidFuel" : 52 | { 53 | "failureTitle" : "Liquid Fuel Leaking", 54 | "failureType" : "mechanical", 55 | "severity" : "failure", 56 | "resourceToLeak" : "LiquidFuel", 57 | "initialAmount" : 10, 58 | "perSecondAmount" : 1 59 | }, 60 | "ResourceLeak_Oxidizer" : 61 | { 62 | "failureTitle" : "Oxidizer Leaking", 63 | "failureType" : "mechanical", 64 | "severity" : "failure", 65 | "resourceToLeak" : "Oxidizer", 66 | "initialAmount" : 10, 67 | "perSecondAmount" : 1 68 | }, 69 | "ResourceLeak_MonoPropellant" : 70 | { 71 | "failureTitle" : "MonoPropellant Leaking", 72 | "failureType" : "mechanical", 73 | "severity" : "failure", 74 | "resourceToLeak" : "MonoPropellant", 75 | "initialAmount" : 1, 76 | "perSecondAmount" : 0.1 77 | }, 78 | "ResourceLeak_Random" : 79 | { 80 | "failureTitle" : "Tank is leaking", 81 | "failureType" : "mechanical", 82 | "severity" : "failure", 83 | "resourceToLeak" : "random", 84 | "initialAmount" : 5, 85 | "perSecondAmount" : 1 86 | } 87 | }, 88 | "TestFlightConfigs" : 89 | { 90 | "Tank" : 91 | { 92 | "TestFlightCore" : 93 | { 94 | "configuration" : "" 95 | }, 96 | "FlightDataRecorder" : 97 | { 98 | "flightDataMultiplier" : 2, 99 | "flightDataEngineerModifier" : 0.05 100 | }, 101 | "TestFlightReliability" : 102 | { 103 | "CURVE_DEF" : "HighReliability" 104 | }, 105 | "TestFlightFailure_Explode" : 106 | { 107 | "FAILURE_DEF" : "Explode", 108 | "weight" : 2 109 | }, 110 | "TestFlightFailure_ResourceLeak" : 111 | { 112 | "FAILURE_DEF" : "ResourceLeak_Random", 113 | "weight" : 32 114 | } 115 | } 116 | }, 117 | "PartConfigs" : 118 | { 119 | "TanksAll" : 120 | { 121 | "patterns" : 122 | [ 123 | "@PART[*]:HAS[@RESOURCE[*]]:FINAL" 124 | ], 125 | "configs" : ["Tank"] 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /configs/Stock/Squad_Tanks.yaml: -------------------------------------------------------------------------------- 1 | # Predefined repair setups so they can be re-used later 2 | RepairConfigs: 3 | - &EasySoftware 4 | canBeRepairedByRemote: true 5 | canBeRepairedInFlight: true 6 | canBeRepairedOnSplashed: true 7 | dataScale: 1 8 | dataSize: 1 9 | repairChance: 75 10 | - &MediumHydraulic 11 | canBeRepairedByRemote: false 12 | canBeRepairedInFlight: false 13 | canBeRepairedOnSplashed: false 14 | repairChance: 50 15 | replacementPart: 'HydraulicGizmo' 16 | replacementPartOptional: true 17 | replacementPartBonus: 0.10 18 | - &EasyMechanical 19 | canBeRepairedByRemote: false 20 | canBeRepairedInFlight: false 21 | canBeRepairedOnSplashed: false 22 | repairChance: 75 23 | FailureConfigs: 24 | - &Explode 25 | failureTitle: 'Explosion!' 26 | failureType: 'mechanical' 27 | duFail: 400 28 | severity: 'major' 29 | - &ResourceLeak_LiquidFuel 30 | failureTitle: 'Liquid Fuel Leaking' 31 | failureType: 'mechanical' 32 | duFail: 25 33 | duRepair: 50 34 | severity: 'failure' 35 | resourceToLeak: 'LiquidFuel' 36 | initialAmount: 10 37 | perSecondAmount: 1 38 | - &ResourceLeak_Oxidizer 39 | failureTitle: 'Oxidizer Leaking' 40 | failureType: 'mechanical' 41 | duFail: 25 42 | duRepair: 50 43 | severity: 'failure' 44 | resourceToLeak: 'Oxidizer' 45 | initialAmount: 10 46 | perSecondAmount: 1 47 | - &ResourceLeak_MonoPropellant 48 | failureTitle: 'MonoPropellant Leaking' 49 | failureType: 'mechanical' 50 | duFail: 25 51 | duRepair: 50 52 | severity: 'failure' 53 | resourceToLeak: 'MonoPropellant' 54 | initialAmount: 1 55 | perSecondAmount: 0.1 56 | - &ResourceLeak_Random 57 | failureTitle: 'Tank is leaking' 58 | failureType: 'mechanical' 59 | duFail: 25 60 | duRepair: 50 61 | severity: 'failure' 62 | resourceToLeak: 'random' 63 | initialAmount: 5 64 | perSecondAmount: 1 65 | PartConfigs: 66 | # Solids 67 | HighReliabilityTank: &HRTank 68 | # Should only ever be ONE Interop module for a unique PART in KSP. 69 | - name: 'TestFlightInterop' 70 | - name: 'TestFlightCore' 71 | maxData: 10000 72 | - name: 'FlightDataRecorder_Resources' 73 | flightDataMultiplier: 10 74 | flightDataEngineerModifier: 0.25 75 | - name: 'TestFlightReliability' 76 | reliabilityCurve: 77 | - '0 0.00015' 78 | - '10000 0.00002' 79 | # When referencing a block like this for use in a module, the blocks have to come BEFORE the module itself. They will then get folded down into it 80 | - *ResourceLeak_Random 81 | - name: 'TestFlightFailure_ResourceLeak' 82 | weight: 32 83 | - *Explode 84 | - name: 'TestFlightFailure_Explode' 85 | weight: 2 86 | StartingTank: &StartTank 87 | # Should only ever be ONE Interop module for a unique PART in KSP. 88 | - name: 'TestFlightInterop' 89 | - name: 'TestFlightCore' 90 | maxData: 10000 91 | startFlightData: 10000 92 | - name: 'FlightDataRecorder_Resources' 93 | flightDataMultiplier: 10 94 | flightDataEngineerModifier: 0.25 95 | - name: 'TestFlightReliability' 96 | reliabilityCurve: 97 | - '0 0.00015' 98 | - '10000 0.00002' 99 | # When referencing a block like this for use in a module, the blocks have to come BEFORE the module itself. They will then get folded down into it 100 | - *ResourceLeak_Random 101 | - name: 'TestFlightFailure_ResourceLeak' 102 | weight: 32 103 | - *Explode 104 | - name: 'TestFlightFailure_Explode' 105 | weight: 2 106 | Parts: 107 | - part: 'ResourceTank' 108 | patterns: 109 | - '@PART[*]:HAS[!MODULE[ModuleCommand],@RESOURCE[*]]' 110 | configs: 111 | - *HRTank 112 | -------------------------------------------------------------------------------- /configs/compileConfigs.py: -------------------------------------------------------------------------------- 1 | # This utility script compiles TestFlight configurations into final proper ModuleManager config files 2 | 3 | import os, argparse, sys, json, glob 4 | 5 | ALL_BODIES = [ 6 | "sun", 7 | "moho", 8 | "eve", 9 | "gilly", 10 | "kerbin", 11 | "min", 12 | "minmus", 13 | "duna", 14 | "ike", 15 | "dres" 16 | "jool", 17 | "laythe", 18 | "vall", 19 | "tylo", 20 | "bop", 21 | "pol", 22 | "eeloo" 23 | ] 24 | 25 | ALL_SITUATIONS = [ 26 | "atmosphere", 27 | "space" 28 | ] 29 | 30 | ALL_SCOPES = [ 31 | "deep_space" 32 | ] 33 | 34 | class DefaultHelpParser(argparse.ArgumentParser): 35 | def error(self, message): 36 | sys.stderr.write('error: %s\n' % message) 37 | self.print_help() 38 | sys.exit(2) 39 | 40 | def loadJSON(jsonFilename): 41 | with open(jsonFilename, "r") as jsonFile: 42 | rawJson = json.load(jsonFile) 43 | return rawJson 44 | 45 | def compileFailureDef(d): 46 | definition = rawJson["FailureConfigs"][d] 47 | node = "" 48 | for key in definition: 49 | node += "\n\t\t{} = {}".format(key, definition[key]) 50 | return node 51 | 52 | def compileRepairDef(d): 53 | definition = rawJson["RepairConfigs"][d] 54 | node = "\n\t\tREPAIR\n\t\t{" 55 | for key in definition: 56 | node += "\n\t\t\t{} = {}".format(key, definition[key]) 57 | node += "\n\t\t}" 58 | return node 59 | 60 | def compileCurveDef(d): 61 | definition = rawJson["ReliabilityDefinitions"][d] 62 | # build reliability curves for each scope unless its overridden 63 | configNodes = "" 64 | for scope in definition: 65 | configNodes += "\n\t\tRELIABILITY_BODY\n\t\t{" 66 | configNodes += "\n\t\t\tscope = " + scope 67 | configNodes += "\n\t\t\treliabilityCurve" 68 | configNodes += "\n\t\t\t{" 69 | for key in definition[scope]: 70 | configNodes += "\n\t\t\t\t" + key 71 | configNodes += "\n\t\t\t}" 72 | configNodes += "\n\t\t}" 73 | return configNodes 74 | 75 | def compile(pattern, config): 76 | configDef = rawJson["TestFlightConfigs"][config] 77 | node = "\n" + pattern + "\n{" 78 | if not "TestFlightCore" in configDef: 79 | node += "\n\tMODULE\n\t{\n\t\tname = TestFlightCore\n\t}\n" 80 | 81 | for moduleName in configDef: 82 | moduleConfig = configDef[moduleName] 83 | node += "\n\tMODULE\n\t{\n\t\tname = " + moduleName 84 | for key in moduleConfig: 85 | if key == "CURVE_DEF": 86 | node += compileCurveDef(moduleConfig[key]) 87 | elif key == "REPAIR_DEF": 88 | node += compileRepairDef(moduleConfig[key]) 89 | elif key == "FAILURE_DEF": 90 | node += compileFailureDef(moduleConfig[key]) 91 | else: 92 | if isinstance(moduleConfig[key], dict): 93 | node += "\n\t\t" + key 94 | node += "\n\t\t{" 95 | for subKey in moduleConfig[key]["keys"]: 96 | node += "\n\t\t\t" + subKey 97 | node += "\n\t\t}" 98 | else: 99 | node += "\n\t\t{} = {}".format(key, moduleConfig[key]) 100 | node += "\n\t}" 101 | node += "\n}" 102 | return node 103 | 104 | 105 | HELP_DESC = "Compiles a given TestFlight config.json to standard ModuleManager.cfg" 106 | parser = DefaultHelpParser(description=HELP_DESC) 107 | parser.add_argument('directory', metavar='directory', type=str, nargs=1, 108 | help='directory containing .json configs to compile') 109 | 110 | args = parser.parse_args() 111 | 112 | # print args 113 | 114 | if not args.directory or len(args.directory) < 1: 115 | print "ERROR: No configuration directory specified. Configuration directory must be specified." 116 | sys.exit(2) 117 | 118 | configs = glob.glob(args.directory[0] + "/*.json") 119 | 120 | for jsonFile in configs: 121 | print "PROCESSING " + jsonFile 122 | rawJson = loadJSON(jsonFile) 123 | 124 | # Init scopes 125 | for body in ALL_BODIES: 126 | for situation in ALL_SITUATIONS: 127 | ALL_SCOPES.append(body + "_" + situation) 128 | 129 | # Process each defined part config 130 | finalConfig = "" 131 | for partConfig in rawJson["PartConfigs"].values(): 132 | configs = partConfig["configs"] 133 | patterns = partConfig["patterns"] 134 | for pattern in patterns: 135 | for config in configs: 136 | finalConfig += compile(pattern, config) 137 | 138 | baseName = os.path.splitext(jsonFile)[0] 139 | with open(baseName + ".cfg", "w") as cfgFile: 140 | cfgFile.write(finalConfig) 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /configs/compileYamlConfigs.py: -------------------------------------------------------------------------------- 1 | import os, argparse, sys, json, glob, pprint 2 | import yaml 3 | 4 | class DefaultHelpParser(argparse.ArgumentParser): 5 | def error(self, message): 6 | sys.stderr.write('error: %s\n' % message) 7 | self.print_help() 8 | sys.exit(2) 9 | 10 | def load(filename): 11 | with open(filename, "r") as f: 12 | data = yaml.load(f) 13 | return data 14 | 15 | def compileConfigNode(name, node, depth = 2): 16 | nodeString = "" 17 | nodeString += '\t' * depth 18 | nodeString += name + '\n' 19 | nodeString += '\t' * depth 20 | nodeString += "{\n" 21 | 22 | for key,value in node.iteritems(): 23 | if isinstance(value,dict): 24 | nodeString += compileConfigNode(key, value, depth + 1) 25 | elif isinstance(value,list): 26 | nodeString += '\t' * (depth + 1) 27 | nodeString += key + '\n' 28 | nodeString += '\t' * (depth + 1) 29 | nodeString += "{\n" 30 | for item in value: 31 | nodeString += '\t' * (depth + 2) 32 | nodeString += "key = {}\n".format(item) 33 | nodeString += '\t' * (depth + 1) 34 | nodeString += "}\n" 35 | else: 36 | nodeString += '\t' * (depth + 1) 37 | nodeString += "{} = {}\n".format(key, value) 38 | 39 | nodeString += '\t' * depth 40 | nodeString += "}\n" 41 | return nodeString 42 | 43 | def compileFloatCurve(name, node, depth = 2): 44 | nodeString = "" 45 | nodeString += '\t' * (depth) 46 | nodeString += name + '\n' 47 | nodeString += '\t' * (depth) 48 | nodeString += "{\n" 49 | for item in node: 50 | nodeString += '\t' * (depth + 1) 51 | nodeString += "key = {}\n".format(item) 52 | nodeString += '\t' * (depth) 53 | nodeString += "}\n" 54 | return nodeString 55 | 56 | def compile(pattern, partConfig, data): 57 | cachedModule = {} 58 | moduleString = pattern + "\n{\n" 59 | for module in partConfig: 60 | if not "name" in module: 61 | cachedModule = module 62 | continue 63 | if cachedModule != None and len(cachedModule) > 1: 64 | module.update(cachedModule) 65 | cachedModule = {} 66 | moduleString += "\n\tMODULE\n\t{\n" 67 | for key,value in module.iteritems(): 68 | if isinstance(value,list): 69 | if isinstance(value[0],dict): 70 | for node in value: 71 | if isinstance(node,dict): 72 | moduleString += compileConfigNode(key, node) 73 | else: 74 | moduleString += compileFloatCurve(key, value, 2) 75 | else: 76 | moduleString += "\t\t{} = {}\n".format(key,value) 77 | moduleString += "\t}" 78 | moduleString += "\n}\n" 79 | return moduleString 80 | 81 | 82 | HELP_DESC = "Compiles a given TestFlight Config YAML to standard ModuleManager.cfg" 83 | parser = DefaultHelpParser(description=HELP_DESC) 84 | parser.add_argument('directory', metavar='directory', type=str, nargs=1, 85 | help='directory containing .yaml configs to compile') 86 | 87 | args = parser.parse_args() 88 | 89 | # print args 90 | 91 | if not args.directory or len(args.directory) < 1: 92 | print "ERROR: No configuration directory specified. Configuration directory must be specified." 93 | sys.exit(2) 94 | 95 | configs = glob.glob(args.directory[0] + "/*.yaml") 96 | 97 | for yamlFile in configs: 98 | print "PROCESSING " + yamlFile 99 | finalConfig = "" 100 | data = load(yamlFile) 101 | 102 | pp = pprint.PrettyPrinter(indent=2,width=120) 103 | # pp.pprint(data) 104 | 105 | parts = data["Parts"] 106 | for part in parts: 107 | print "\tProcessing part: ", part["part"] 108 | patterns = part["patterns"] 109 | configs = part["configs"] 110 | for pattern in patterns: 111 | for config in configs: 112 | finalConfig += compile(pattern, config, data) 113 | 114 | baseName = os.path.splitext(yamlFile)[0] 115 | print "WRITING " + baseName + ".cfg" 116 | with open(baseName + ".cfg", "w") as cfgFile: 117 | cfgFile.write(finalConfig) 118 | 119 | -------------------------------------------------------------------------------- /custom.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /failureProbabilityPlot.py: -------------------------------------------------------------------------------- 1 | import random 2 | import matplotlib.pyplot as plt 3 | from matplotlib import mlab 4 | 5 | 6 | def roll(): 7 | total = 0 8 | rolls = [] 9 | for i in range(0,10): 10 | rolls.append(random.randint(1,20)) 11 | # print "Base rolls ",sorted(rolls) 12 | sortedRolls = sorted(rolls) 13 | rolls = sortedRolls[:5] 14 | # print "Reduced Rolls ", sorted(rolls) 15 | final = rolls[0] + rolls[1] + rolls[2] + rolls[3] + rolls[4] 16 | # final = final - 5 17 | # print final 18 | return final 19 | 20 | def generateRolls(count): 21 | allRolls = [] 22 | for i in range(0, count): 23 | allRolls.append(roll()) 24 | return allRolls 25 | 26 | x = generateRolls(1000) 27 | # print sorted(x)[0] 28 | # print sorted(x)[1000/2] 29 | # print sorted(x)[-1] 30 | 31 | n_bins = 100 32 | n, bins, patches = plt.hist(x, n_bins, normed=True, histtype='bar', cumulative=False) 33 | 34 | # Add a line showing the expected distribution. 35 | # y = mlab.normpdf(bins, mu, sigma).cumsum() 36 | # y /= y[-1] 37 | # plt.plot(bins, y, 'k--', linewidth=1.5) 38 | 39 | # Overlay a reversed cumulative histogram. 40 | # plt.hist(x, bins=bins, normed=1, histtype='step', cumulative=-1) 41 | 42 | plt.grid(True) 43 | # plt.xticks(range(0,20)) 44 | plt.ylim(0, 1) 45 | plt.title('Failure Module Probability') 46 | 47 | plt.show() -------------------------------------------------------------------------------- /makeMeta.py: -------------------------------------------------------------------------------- 1 | import os, argparse, sys, json, glob 2 | 3 | class DefaultHelpParser(argparse.ArgumentParser): 4 | def error(self, message): 5 | sys.stderr.write('error: %s\n' % message) 6 | self.print_help() 7 | sys.exit(2) 8 | 9 | HELP_DESC = "Creates neccesary metadata files" 10 | parser = DefaultHelpParser(description=HELP_DESC) 11 | parser.add_argument('tag', metavar='tag', type=str, nargs=1, 12 | help='tag of release (e.g. 0.4.6.0') 13 | 14 | args = parser.parse_args() 15 | 16 | if not args.tag or len(args.tag) < 1: 17 | print("ERROR: git tag must be specified and must be in the format major.minor.patch.build-configuration.e.g. 0.4.6.0") 18 | sys.exit(2) 19 | 20 | version = args.tag[0] 21 | 22 | if version.startswith('v'): 23 | version = version.split('v')[1] 24 | 25 | major = int(version.split(".")[0]) 26 | minor = int(version.split(".")[1]) 27 | patch = int(version.split(".")[2]) 28 | build = int(version.split(".")[3]) 29 | # create AVC .version file 30 | avc = { 31 | "NAME" : "TestFlight", 32 | "URL" : "http://ksp-avc.cybutek.net/version.php?id=118", 33 | "DOWNLOAD" : "https://github.com/KSP-RO/TestFlight/releases/download/{}/TestFlight-{}.zip".format(args.tag[0],args.tag[0]), 34 | "CHANGE_LOG_URL" : "https://raw.githubusercontent.com/KSP-RO/TestFlight/master/RELEASE_NOTES_RAW.txt", 35 | "VERSION" : 36 | { 37 | "MAJOR" : major, 38 | "MINOR" : minor, 39 | "PATCH" : patch, 40 | "BUILD" : build 41 | }, 42 | "KSP_VERSION_MIN" : 43 | { 44 | "MAJOR" : 1, 45 | "MINOR" : 12, 46 | "PATCH" : 0 47 | }, 48 | "KSP_VERSION_MAX" : 49 | { 50 | "MAJOR" : 1, 51 | "MINOR" : 12, 52 | "PATCH" : 99 53 | } 54 | } 55 | with open("TestFlight.version", "w") as f: 56 | f.write(json.dumps(avc, indent=4)) 57 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | PROJ_NAME = $(shell basename `pwd`) 3 | CONFIG_DIR = configs 4 | VERSION = $(shell git describe --tags) 5 | BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>&1) 6 | BINS = https://ksp-ro.s3-us-west-2.amazonaws.com/TestFlight_bin_KSP-1.10.zip 7 | 8 | ZIP_CORE := TestFlightCore 9 | 10 | $(info Travis Branch: $(TRAVIS_BRANCH)) 11 | $(info Travis Tag: $(TRAVIS_TAG)) 12 | ifdef TRAVIS_BRANCH 13 | ifeq "$(TRAVIS_BRANCH)" "master" 14 | ZIP_CORE := $(ZIP_CORE)-release_$(TRAVIS_BUILD_NUMBER) 15 | else ifeq "$(TRAVIS_BRANCH)" "dev" 16 | ZIP_CORE := $(ZIP_CORE)-prerelease_$(TRAVIS_BUILD_NUMBER) 17 | else 18 | ZIP_CORE := $(ZIP_CORE)-dev_$(TRAVIS_BUILD_NUMBER) 19 | endif 20 | endif 21 | 22 | ifdef TRAVIS_TAG 23 | ZIP_CORE := $(ZIP_CORE)-$(TRAVIS_TAG) 24 | endif 25 | 26 | ZIP_CORE := $(ZIP_CORE).zip 27 | 28 | $(info $(ZIP_CORE)) 29 | all: clean meta 30 | 31 | ifdef TRAVIS_TAG 32 | release: zip 33 | else 34 | release: 35 | endif 36 | 37 | ifdef TRAVIS_TAG 38 | meta: 39 | python makeMeta.py $(TRAVIS_TAG) 40 | cp TestFlight.version GameData/TestFlight/TestFlight.version 41 | else 42 | meta: 43 | endif 44 | 45 | zip: meta 46 | zip $(ZIP_CORE) GameData GameData/TestFlight/* GameData/TestFlight/Plugins/* GameData/TestFlight/Resources/* GameData/TestFlight/Resources/Textures/* -x ignore.txt 47 | mkdir builds/ 48 | cp $(ZIP_CORE) builds/$(ZIP_CORE) 49 | 50 | 51 | clean: 52 | -rm *.zip 53 | -rm GameData/TestFlight/*.version 54 | -rm GameData/TestFlight/*.ckan 55 | -rm *.version 56 | -rm *.ckan 57 | 58 | getBins: 59 | pwd 60 | curl $(BINS) --output bins.zip 61 | unzip -P $(ZIP_PW) bins.zip 62 | msbuild /p:Configuration=Release /p:ReferencePath=/home/travis/build/KSP-RO/TestFlight/bin/Release TestFlight.sln -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | TestFlight 2 | ========== 3 | Release: [![Build Status Master](https://travis-ci.org/KSP-RO/TestFlight.svg?branch=master)](https://travis-ci.org/KSP-RO/TestFlight) 4 | 5 | Prerelease: [![Build Status dev](https://travis-ci.org/KSP-RO/TestFlight.svg?branch=dev)](https://travis-ci.org/KSP-RO/TestFlight) 6 | 7 | 8 | ---------------------------------- 9 | 10 | # TestFlight 11 | ### A configurable, extensible, parts research and reliability system for Kerbal Space Program (KSP). 12 | 13 | --- 14 | 15 | ## Release Details 16 | Please see Github releases or CKAN for installation. Note, do **NOT** simply download the repository. That will not work! 17 | 18 | ## License 19 | TestFlight is released on the Creative Commons 4.0 by-nc-sa License. 20 | 21 | http://creativecommons.org/licenses/by-nc-sa/4.0/ 22 | 23 | ## What Is TestFlight? 24 | TestFlight is a persistent, parts based, research and reliability system. It gives you a reason to do test flights of your rockets. Test flights let your engineers generate flight data, which can then be analyzed to further improve the reliability of your rocket parts. Flight data generated on a part is persistent, and carries over to new rockets flown with those parts. 25 | 26 | In a nutshell; Fly your parts more, generate flight data, get more reliable parts. But TestFlight is much more! 27 | 28 | ## FlightData 29 | The more you fly parts, the more flight data they record, which in turns improves reliability. As stated, this is persistent. That means that if you launch a "Super Rocket 1" with a Mainsail engine, that mainsail generates let's say 10,000 units of flight data. Now you go back to the VAB and build "Super Rocket 2" which also uses the mainsail. That instance of the mainsail starts with 10,000 units of flight data already from the earlier flight. That means test flights make your rockets more relable! 30 | 31 | ## Reliability and Failures 32 | TestFlight calculates reliability using the flight data recorded by a part, based on various criteria and mathemtical equations. It will periodicly make failure checks against this data and if a part is determined to have failed, it will generate failure events. 33 | 34 | ## TestFlight is Configurable and Extensible 35 | The real beauty of TestFlight is that it is extremely configurable by the end user, or by mod authors who want to integrate it into thier own mods. TestFlight works on a series of pluggable PartModules that give full control over how reliability is calculated and what failures are possible - all on a per part basis if desired. Further more, all of the various options can be configured by the user or mod authors, such as minimum and maximum reliability ratings, failure rates, repair costs, and more. 36 | 37 | On top of all that, TestFlight comes with a public API that allows mod authors to further extend the system! Mod authors can easily add additional failure types, or change how flight data is recorded, or how reliability is calculated. The API for example could allow a mod auther to easily extend the system to penalize the reliability of individual parts as they get old. 38 | -------------------------------------------------------------------------------- /release_checklist.md: -------------------------------------------------------------------------------- 1 | TestFlight Release Checklist 2 | ============================ 3 | 4 | To prevent mistakes this checklist must be followed every time a release is done! 5 | To start a release, open an issue on GitHub with the contents of the below: 6 | 7 | TestFlight Release X.X.X.X 8 | ========================== 9 | 10 | - [ ] Determine proper version number 11 | - [ ] Verify good Travis build 12 | - [ ] Change log in Markdown 13 | - [ ] Change log in BBCode 14 | - [ ] Github Release Tag 15 | - [ ] Forum OP Change Log updated 16 | - [ ] Forum OP Title updated 17 | - [ ] New reply in Forum thread with Change Log and any important notes 18 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PyYAML==5.4 2 | --------------------------------------------------------------------------------