Jump to content

[0.90] TestFlight [0.4.6.1][04FEB15] -Configurable, extensible, parts research & reliability system


Agathorn

What are would you like to see focused on next  

73 members have voted

  1. 1. What are would you like to see focused on next

    • Improving the GUI and Player Experience
      17
    • Adding new Core Failure modules
      10
    • Adding configs to enable TestFlight with all stock parts
      22
    • Adding configs to enable TestFlight with popular part packs
      37


Recommended Posts

First alpha version of TestFlight has now been released! You can find v0.1.0 on the GitHub page, as linked in the Original Post, and below.

v0.1.0 Alpha

https://github.com/jwvanderbeck/TestFlight/releases/tag/v0.1.0

Please, please, note that this is an initial alpha release and is no doubt buggy as hell. Don't use it in any save game that you care about, and fully expect newer versions to break your saves.

This initial release only contains a few failure modules for engines and fuel tanks. I plan to expand the system in the future. I welcome any ideas on failure types people would like to see implemented.

I have done major edits to the original post to summarize all the information, and what not. Please take a moment to look it over.

Any feedback, questions, etc please post. Thanks!

Link to comment
Share on other sites

Extending TestFlight - A Guide for Modders

TestFlight is a mod for KSP, but TestFlight itself is designed to be moddable as well. This allows other modders the ability to extend the TestFlight system by adding new modules for Data Recording, Reliability checks, and Failure Modes. This documentation is geared towards modders who want to extend the TestFlight system in some way.

Core Architecture

TestFlight works on a per-part basis and is comprised of four basic modules.

TestFlight Core

The core module which runs the entire system for that part. TestFlightCore can not be extended.

FlightDataRecorder

In a nutshell, TestFlight is a system whereby you fly parts and they record data. The FlightDataRecorder module is what handles recording of the flight data. If you want to control how data is recorded, then you can extend FlightDataRecorder to make your own recorder. The base module is very simple, and simply records data as long as the part is enabled.

TestFlightReliability

This module is responsible for determining the part's reliability. The base TestFlightReliability module simply determines reliability based on the collected flight data. By creating your own Reliability module, you can add to or remove from this base reliability based on other criteria. For example maybe you want a part to become less reliable as it gets hotter. There can be multiple Reliability modules on a part, and the TestFlightCore simply polls them all, and adds up the reported reliability from each into a total reliability.

TestFlightFailure

The module most likely to be extended, the TestFlightFailure module defines a specific failure that can occur on a part. Maybe the part explodes, or leaks fuels, or shuts down. Whatever you want to happen as a possible failure on the part, you can do it by making a Failure module.

Writing Your Own Modules

Writing your own modules to extend TestFlight is very easy. Simply make a standard KSP PartModule, and Implement the required TestFlightAPI Interface for the TestFlight module you want to make. IFlightDataRecorder, ITestFlightReliability, or ITestFlightFailure. To make things even easier, you can inherit from the base TestFlight module for each, where most of the work to interface with the overall system will be handled for you, and you just need to implement the specific logic for your module.

Common Data Structures

TestFlightData


public struct TestFlightData
{
// Scope is a combination of the current SOI and the Situation, always lowercase.
// EG "kerbin_atmosphere" or "mun_space"
// The one exception is "deep-space" which applies regardless of the SOI if you are deep enough into space
public string scope;
// The total accumulated flight data for the part
public float flightData;
// The specific flight time, in seconds, of this part instance
public int flightTime;
}

The TestFlightData structure is used to move flight data around between modules.

TestFlightFailureDetails


public struct TestFlightFailureDetails
{
// Human friendly title to display in the MSD for the failure. 25 characters max
public string failureTitle;
// "minor", "failure", or "major" used to indicate the severity of the failure to the player
public string severity;
// chances of the failure occuring relative to other failure modules on the same part
// This should never be anything except:
// 2 = Rare, 4 = Seldom, 8 = Average, 16 = Often, 32 = Common
public int weight;
// "mechanical" indicates a physical failure that requires physical repair
// "software" indicates a software or electric failure that might be fixed remotely by code
public string failureType;
// Indicates in broad sense, is it ever possible to attempt a repair under some condition?
public bool canBeRepaired;
// Repair details
// Time required to complete repairs. Not currently supported.
public int repairTimeRequired;
// For mechanical failures
// Does the repair require that a Kerbal be EVA to repair the part?
public bool requiresEVA;
// Can the part be repaired while the vessel is in flight?
public bool canBeRepairedInFlight;
// Can the part be repaired when the vessel is landed on the surface?
public bool canBeRepairedOnLanded;
// Can the part be repaired when the vessel is splashed down in the water?
public bool canBeRepairedOnSplashed;
// How many spare parts does it take to attempt repair?
public int sparePartsRequired;
// For software failures
// Can the part be repaired by remote?
public bool canBeRepairedByRemote;
}

This structure closely, but not exactly, mimics the variables contained in the config module for a failure. It is used to allow communication of failure details between modules that need it.

Interfaces

IFlightDataRecorder


public interface IFlightDataRecorder
{
/// <summary>
/// Called frequently by TestFlightCore to ask the module for the current flight data.
/// The module should only return the currently active scope's data, and should return the most up
/// to date data it has.
/// This method should only RETURN the current flight data, not calculate it. Calculation
/// should be done in DoFlightUpdate()
/// </summary>
/// <returns>The current flight data.</returns>
TestFlightData GetCurrentFlightData();

/// <summary>
/// Initializes the flight data on a newly instanced part from the stored persistent flight data.
/// This data should only be accepted the first time ever.
/// </summary>
/// <param name="allFlightData">A list of all TestFlightData stored for the part, once for each known scope</param>
void InitializeFlightData(List<TestFlightData> allFlightData);

/// <summary>
/// Called to set what is considered "deep-space" altitude
/// </summary>
/// <param name="newThreshold">New threshold.</param>
void SetDeepSpaceThreshold(double newThreshold);

/// <summary>
/// Called frequently by TestFlightCore to let the DataRecorder do an update cycle to calulate the current flight data.
/// This is where the calculation of current data based on paremeters (such as elapsed MET) should occur.
/// Generally this will be called immediately prior to GetcurrentFlightData() so that the DataRecorder
/// can be up to date.
/// </summary>
/// <param name="missionStartTime">Mission start time in seconds.</param>
/// <param name="flightDataMultiplier">Global Flight data multiplier. A user setting which should modify the internal collection rate. Amount of collected data should be multiplied against this. Base is 1.0 IE no modification.</param>
/// <param name="flightDataEngineerMultiplier">Flight data engineer multiplier. A user setting mutiplier that makes the engineer bonus more or less. 1.0 is base.</param>
void DoFlightUpdate(double missionStartTime, double flightDataMultiplier, double flightDataEngineerMultiplier);

/// <summary>
/// Returns the current data situation, "atmosphere", "space", or "deep-space"
/// </summary>
/// <returns>The Situation of the current data scope</returns>
string GetDataSituation();

/// <summary>
/// Returns current SOI
/// </summary>
/// <returns>The current SOI for the data scope</returns>
string GetDataBody();
}

ITestFlightReliability


public interface ITestFlightReliability
{
/// <summary>
/// Gets the current reliability of the part as calculated based on the given flightData
/// </summary>
/// <returns>The current reliability. Can be negative in order to reduce overall reliability from other Reliability modules.</returns>
/// <param name="flightData">Flight data on which to calculate reliability.</param>
float GetCurrentReliability(TestFlightData flightData);
}

ITestFlightFailure


public interface ITestFlightFailure
{
/// <summary>
/// Gets the details of the failure encapsulated by this module. In most cases you can let the base class take care of this unless oyu need to do somethign special
/// </summary>
/// <returns>The failure details.</returns>
TestFlightFailureDetails GetFailureDetails();

/// <summary>
/// Triggers the failure controlled by the failure module
/// </summary>
void DoFailure();

/// <summary>
/// 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
/// </summary>
/// <returns><c>true</c> if this instance can attempt repair; otherwise, <c>false</c>.</returns>
bool CanAttemptRepair();

/// <summary>
/// Trigger a repair ATTEMPT of the module's failure. It is the module's responsability to take care of any consumable resources, data transmission, etc required to perform the repair
/// </summary>
/// <returns>Should return true if the failure was repaired, false otherwise</returns>
bool AttemptRepair();
}

Project Setup - Compiling Against DLLs, etc

At the current time I haven't exactly worked out how to deal with requiring a mod to compile against the TestFlightAPI DLL or how to handle versioning etc. I am open to any suggestions and help on this anyone can give. I'm not too knowledgeable in this area. Since it works through interfaces, in theory you should not even need to compile against the DLL at all. As long as you implement the proper interfaces, you should be good. However compiling against the DLL is probably easier, and it lets you use the base classes that do most of the work for you rather than having to implement them yourself. Again, thoughts and suggestion on this are most appreciated.

The intention is to through various alpha tests, get the API to a stable spot whereby it will change only infrequently, so it won't be a burden to anyone to keep up with it.

Link to comment
Share on other sites

Part Configs

In order to add the TestFlight system to a part, you simply need to make an appropriate config for the part, just like with many other mods using ModuleManager. An example config with documentation is given below. If you have any questions, please let me know.

Sample Part Config

@PART[liquidEngine]:AFTER[Squad]
{
// The TestFlightCore module is, well, the core of the entire system and controls all the other pieces
// Every part that uses TestFlight *must* have a TestFlightCore module or it won't connect to the
// overall system.
// There should only ever be a SINGLE TestFlightCore module on a part.
MODULE
{
name = TestFlightCore
// By leaving these two frequencies at 0, we simply let the global frequency take over
// We could however make this one part poll, or check for failures, LESS often by setting higher values here
pollingInterval = 0
failureCheckFrequency = 0
}
// The TestFlightRecorder module is the second module required by the system. This module is responsible
// for collecting flight data, and thus the system is pretty useless without it. This module defines
// how the part gains flight data over time.
// There are different types of FlightRecorder modules, and mods can add new ones.
// There should only ever be a SINGLE TestFlightRecorder module on a part.
MODULE
{
name = FlightDataRecorder_Engine
// The data multiplier indicates, ROUGHLY, how many points of Flight Data
// is accumulated per second of Mission Elapsed Time
flightDataMultiplier = 10
// The data engineer modifier is a bonus per level of engineer skill available in the vessel's crew
flightDataEngineerModifier = 0.25
}
// The TestFlightReliability module is responsible for calculating the reliability of the part based
// on flight data and given scope. Again, there can be multiple of these modules, each canculating
// reliability differently.
// You can have MULTIPLE Reliability modules on a single part.
MODULE
{
name = TestFlightReliability
// factor and multiplier control the difficulty curve of the realiabilty value
// reliability = (flightData * realiabilityMultiplier) ^ (1/reliabilityFactor)
reliabilityFactor = 2
reliabilityMultipler = 3
// The module can have one or more RELIABILITY_BODY nodes. Each defines the min and max reliability
// for a given "Scope".
RELIABILITY_BODY
{
scope = kerbin_atmosphere
minReliability = 50
maxReliability = 98
}
RELIABILITY_BODY
{
scope = kerbin_space
minReliability = 35
maxReliability = 95
}
}
// The TestFlightFailure module is the last type of module in the system. Each TestFlightFailure module
// defines a specific type of failure that can occur, and is responsible for causing that failure when
// told to, and for repairing the failure when told to.
MODULE
{
name = TestFlightFailure_ShutdownEngine
// User friendly name to identify the failure in the MSD. Maximum of 25 characters!
failureTitle = Engine Shutdown
// Failure type can be either "mechanical" or "software".
// Mechanical failures are physical failures of parts and require a Kerbal on site to repair it
// Software failures are electrical or software glitches and can be repaired remotely
failureType = mechanical
// Severity of the failure: minor, failure, major
// As a rule of thumb, minor failures should only hinder a vessel or mission, but not directly put it in danger
severity = major
// ** PLEASE USE ONLY THESE WEIGHTS **
// The weight of the failure is how likely it is to occur RELATIVE to other failures defined on the same part
// 2 = Rare, 4 = Seldom, 8 = Average, 16 = Often, 32 = Common
weight = 4
// If the failure can be repaired, then a REPAIR node mst be defined
// If no FAILURE node is defined then hte failure can not be repaired
REPAIR
{
// For PHYSICAL failures
canBeRepairedOnLanded = True
canBeRepairedOnSplashed = False
canBeRepairedInFlight = True
requiresEVA = False
sparePartsRequired = 10
// For SOFTWARE failures
// canBeRepairedByRemote
// dataScale
// dataSize
// For all failures
repairChance = 100
}
}
}

Link to comment
Share on other sites

So for the next release I am working on getting as much of the core functionality in place as possible. By that I mean as many included modules for things like Failures and Reliability as I can, so with nothing but a base install of TestFlight you have a solid experience without any required additional mods.

I am also working on improving the UI and introducing requirements for part repairs.

Link to comment
Share on other sites

I'm going to be making some changes to the Failure interface. As I have started working on implementing repair systems for the failures, I have come to the conclusion that I don't like the interface as it stands.

The current interface was designed mainly to offload most of the "verification" work to the TestFlightCore. The theory being the more TestFlight itself could handle, the less the mod author has to handle and that is always a good thing. Unfortunately the system as designed this way is not flexible enough to my liking and while it does make it easier on the mod authors, it also stifles creativity.

So I am going to be re-working the failure interface a bit. It will now be the responsibility of the failure module to determine for itself if the repair requirements have been met or not, and communicate that back to TestFlight.

I will update the documentation once I am done.

Link to comment
Share on other sites

Rather than specifying individual parts, would it be feasible to say make a MM cfg apply to all engines that use liquidfuel for instance and only specify specific ones if something different from "standard" is wanted for those parts?

Link to comment
Share on other sites

Rather than specifying individual parts, would it be feasible to say make a MM cfg apply to all engines that use liquidfuel for instance and only specify specific ones if something different from "standard" is wanted for those parts?

Totally, and in fact that was how I started. I actually don't recall why I split them out.

Link to comment
Share on other sites

Great! And sounds like we're thinking alike there :) It should also make it automatically apply to mods as well then :)

Well you get too broad with the matching and things might get .. weird. Like you can apply the config to everything with an Engine module, but then you aren't distinguishing between Solid Rockets and Liquid Rockets, which you should. Also I think a more fun setup will have some engines more reliable and some less. I think providing large sweep configs is certainly doable and I will try to get to that point for popular parts pack, but I also think that in the end the best experience will come from tighter tuning and integration from authors.

BTW I remember now why I had separated them. At the time I was unsure how to apply a config only to liquid engines and another to solid rockets, and I wanted them to have different base reliabilities. So I split them into manual entries rather than a wildcard. I am still learning ModuleManager. I know now I could have done something like @PART[liquidEngine*] but I didn't know that at the time.

- - - Updated - - -

this is awesome great job!!!

Thank you very much. Still early days and a lot of work to do.

- - - Updated - - -

Wooohooo very nice...downloading...

Please let me know if you run into any issues or have feedback once you have tried it out. Still a lot of work to do, and there are no doubt tons of bugs at this point :)

Link to comment
Share on other sites

Well you get too broad with the matching and things might get .. weird. Like you can apply the config to everything with an Engine module, but then you aren't distinguishing between Solid Rockets and Liquid Rockets, which you should. Also I think a more fun setup will have some engines more reliable and some less. I think providing large sweep configs is certainly doable and I will try to get to that point for popular parts pack, but I also think that in the end the best experience will come from tighter tuning and integration from authors.

BTW I remember now why I had separated them. At the time I was unsure how to apply a config only to liquid engines and another to solid rockets, and I wanted them to have different base reliabilities. So I split them into manual entries rather than a wildcard. I am still learning ModuleManager. I know now I could have done something like @PART[liquidEngine*] but I didn't know that at the time.

- - - Updated - - -

Thank you very much. Still early days and a lot of work to do.

- - - Updated - - -

Please let me know if you run into any issues or have feedback once you have tried it out. Still a lot of work to do, and there are no doubt tons of bugs at this point :)

I was actually doing some of that last night using MM's HAS command to check for propellant to designate one setting 'group' for any part that uses liguidfuel propellant since only an engine would have propellant and another that use solidfuel propellant. ie. @PART[*]:HAS[@PROPELLANT[LiquidFuel]] :)

Side note question, to remove a chance of explosion on a part would that portion of the cfg code just be removed for that part or is there a veritable setting that needs to be changed instead? I'm adding a reliability for water tanks from TAC-LS for a chance to leak but doesn't seem likely water would explode. :)

Link to comment
Share on other sites

I was actually doing some of that last night using MM's HAS command to check for propellant to designate one setting 'group' for any part that uses liguidfuel propellant since only an engine would have propellant and another that use solidfuel propellant. ie. @PART[*]:HAS[@PROPELLANT[LiquidFuel]] :)

Oh very cool! Like I Said still learning the real tricks and power of MM so I didn't know you could do that!

Side note question, to remove a chance of explosion on a part would that portion of the cfg code just be removed for that part or is there a veritable setting that needs to be changed instead? I'm adding a reliability for water tanks from TAC-LS for a chance to leak but doesn't seem likely water would explode. :)

Just remove the TestFlightFailure_Explode module from the part you don't want to have any chance of exploding. Basically the system will select from any failure module on the part, so just put on only the ones you want it to choose from.

Link to comment
Share on other sites

Added a list of current available core TestFlight modules to the Original Post, and here as well for reference:

Current Core Modules

While the system can be extended by other mods, TestFlight itself ships with a core set of modules. This is its current state.

Core Data Recorder Modules

  • FlightDataRecorder - Records data at a low rate at all times
  • FlightDataRecorder_Engine - Records data only when an engine is active and thrusting
  • FlightDataRecorder_Resource - Records data only while the part has stored resources. Once empty (with threshold) it stops recording data

Core Reliability Modules

  • TestFlightReliability - Standard reliability calculation based on flight data. Reliability calculated on an increasingly sharper curve.

Core Failure Modules

  • TestFlightFailure_Explode - Part explodes when failure occurs
  • TestFlightFailure_LiquidFuelLeak - Part leaks LiquidFuel when failure occurs. A large initial leak followed by a small per second leak until repaired.
  • TestFlightFailure_LockGimbal - The engine's gimbal fails and gimbal range is set to 0 until repaired
  • TestFlightFailure_ReducedMaxThrust - The engine's maximum thrust is reduced by 50% until repaired
  • TestFlightFailure_ResourceLeak - Part leaks either a random stored resource, or a specified one. Large initial leak followed by a small per second leak until repaired.
  • TestFlightFailure_ShutdownEngine - Engine shuts down until repaired and restarted.

NOTE Some of these are coming in the next release.

- - - Updated - - -

Added a poll to help me focus my time after I finish up the current work on fleshing out the repair system. I would appreciate everyone's thoughts. Thanks for your support!

Edited by Agathorn
Link to comment
Share on other sites

While I'm certainly no expert I'm more that happy to provide suggestions for MM code that you could use if that would help :) Here are some which I hope may benefit you:

Add the engine testing to all engines that use liquid fuel:

@PART[*]:HAS[@MODULE[ModuleEngines],@PROPELLANT[LiquidFuel]]

Add the same to all engines to use solid fuel:

@PART[*]:HAS[@MODULE[ModuleEngines],@PROPELLANT[solidFuel]]

Add the fuel tank stuff to all parts listed as a fuel tank that contain any resource (ie not fuel line, etc.):

@PART[*]:HAS[#category[FuelTank],@RESOURCE[*]]

Add tank stuff for any oxygen tank except for command modules (call them a protected emergency system :) ):

@PART[*]:HAS[@RESOURCE[Oxygen],!MODULE[ModuleCommand]]

same idea for water:

@PART[*]:HAS[@RESOURCE[Water],!MODULE[ModuleCommand]]

Link to comment
Share on other sites

Having a problem with the GUI not showing up in any screen. Clicking the toolbar icon just quickly flashes a small square but nothing more. Debug pops a "[Log]: TestFlightManagerScenario: Removing 0 vessels from Master Status" entry a few times after clicking the button but that's all. Possible conflict or corrupt download?

Link to comment
Share on other sites

Having a problem with the GUI not showing up in any screen. Clicking the toolbar icon just quickly flashes a small square but nothing more. Debug pops a "[Log]: TestFlightManagerScenario: Removing 0 vessels from Master Status" entry a few times after clicking the button but that's all. Possible conflict or corrupt download?

If it isn't showing up, it sounds like it isn't detecting any parts with TestFlight status. Could be your configs if you have been making your own, or could (likely) be a bug. Can I get a full dump of your log on Dropbox or something?

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...