Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

Has anyone developed mods to with deployable trusses or tethers? I see that Infernal Robotics allows you to link parts of a spacecraft together with rotating parts. I'm looking for something with connecting parts that expand.

Kerbal Attachment System has struts and pipes that can be linked on EVA.

Link to comment
Share on other sites

Kerbal Attachment System has struts and pipes that can be linked on EVA.

Cool, thanks. I was looking for something to link multiple solar sails together into a linear chain for hauling large payloads, and this could work using EVAs and on-orbit assembly.

Link to comment
Share on other sites

Hello all, I'm wondering if anyone could help me figure out a stock ApplicationLauncher issue. I've been playing with it for the better part of a day, switching all kinds of stuff around. The problem started as multiple icons but is now just sometimes having the icon viewable in both the Flight/MapView views instead of just MapView. I've provided the current code below and a tl:dr summary of perhaps related memory management points of file the in the spoiler.

Current core file: https://github.com/rmpalomino/mapviewplus/blob/master/src/MapViewPlus.cs

I only want my ApplicationLauncherButton to be visible in the MapView scene, so I'm following this process:

Start addon only once in MainMenu scene.

In Awake: I register functions for onGUIApplication...Ready/Destroy. I make the GameObject persistent through scenes.

In the onGUI...Ready callback, I call AddModApplication(..., ApplicationLauncher.AppScenes.MAPVIEW, ...) and store the returned ApplicationLauncherButton in a static field.

In the onGUI...Destroy callback, I no longer cleanup the ApplicationLauncherButton.

I leave a stock craft on the Launchpad so I can easily enter the Flight scene. When I enter the Flight view there's no button, I enter MapView and there is a button. I go back to the Space Center, then back to the craft at the Launchpad and sometimes the button is still there. If it is, when I go to MapView and quick toggle the button on and off and return to the Space Center, the button is no longer there in the Flight view.

One other question that I'm not sure where to ask, is there a specific place in the forums where we can ask if there's already a mod dedicated to adding some functionality?

Link to comment
Share on other sites

Hello all, I'm wondering if anyone could help me figure out a stock ApplicationLauncher issue. I've been playing with it for the better part of a day, switching all kinds of stuff around. The problem started as multiple icons but is now just sometimes having the icon viewable in both the Flight/MapView views instead of just MapView. I've provided the current code below and a tl:dr summary of perhaps related memory management points of file the in the spoiler.

Current core file: https://github.com/rmpalomino/mapviewplus/blob/master/src/MapViewPlus.cs

I only want my ApplicationLauncherButton to be visible in the MapView scene, so I'm following this process:

Start addon only once in MainMenu scene.

In Awake: I register functions for onGUIApplication...Ready/Destroy. I make the GameObject persistent through scenes.

In the onGUI...Ready callback, I call AddModApplication(..., ApplicationLauncher.AppScenes.MAPVIEW, ...) and store the returned ApplicationLauncherButton in a static field.

In the onGUI...Destroy callback, I no longer cleanup the ApplicationLauncherButton.

I leave a stock craft on the Launchpad so I can easily enter the Flight scene. When I enter the Flight view there's no button, I enter MapView and there is a button. I go back to the Space Center, then back to the craft at the Launchpad and sometimes the button is still there. If it is, when I go to MapView and quick toggle the button on and off and return to the Space Center, the button is no longer there in the Flight view.

One other question that I'm not sure where to ask, is there a specific place in the forums where we can ask if there's already a mod dedicated to adding some functionality?

onGUIApplicationLauncherReady does not appear to work as it used to. Running the creation code in OnStart (be sure to check whether the button exists already) and the destruction code in OnDestroy appears to produce the required result. See this for an example.

Link to comment
Share on other sites

Is there any way to see what mode/difficulty the current game is in? Would like to use it in my plugins for creating a better experience. It could just be modes (sandbox/career/science) but preferably also difficulties (easy/normal/hard).

Link to comment
Share on other sites

Is there any way to see what mode/difficulty the current game is in? Would like to use it in my plugins for creating a better experience. It could just be modes (sandbox/career/science) but preferably also difficulties (easy/normal/hard).

HighLogic.CurrentGame.Mode can be queried for the current game mode.

HighLogic.CurrentGame.Parameters is where you find the other settings. specifically HighLogic.CurrentGame.Parameters.preset for the preset settings. Otherwise you have to query the parameters.

Link to comment
Share on other sites

Anyone know how to display an interger in a part's editor context menu?


public class MyPartModule : PartModule
{
...

[KSPField(guiActiveEditor=true)]
public int myInt = 42;

...
}

myInt will display in the part's right click menu in the editor, and will change the value when you change it.

Link to comment
Share on other sites

I am trying to bring a unmaintained mod into 1.0.4 and add some new features to it, but I can't seem to get the menus to show up in game in the R click menu. Here is the code in question. It is a fork of the AVTOL mod. Thanks!


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using KSP;
using RealFuels;
using AJE;




namespace AVTOL
{
public class AVTOL:PartModule
{
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float pitchNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float pitchRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float rollNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float rollRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Phase Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float phaseAngle = 90f;

[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Max Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float maxAngle = 90f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Step Angle"),
UI_FloatRange(minValue = -90f, maxValue = 90f, stepIncrement = 0.5f)]
public float stepAngle = 22.5f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Vertical Cutoff"),
UI_FloatRange(minValue = 1f, maxValue = 100f, stepIncrement = 1f)]
public float verticalspeed = 100f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL setting:"),
UI_Toggle(disabledText = "Off", enabledText = "On")]
public bool showMenu = true;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL system:"),
UI_Toggle(disabledText = "Off", enabledText = "Engaged")]
public bool isEngaged = false;


[KSPAction("Toggle VTOL system")]
public void toggleSystem(KSPActionParam param)
{
isEngaged = !isEngaged;
print("VTOL Control System is " + (isEngaged ? "Engaged" : "Off"));
if(!isEngaged)
{
SetThrustPercentage(100f);
}
}
[KSPAction("Increase Phase Angle")]
public void increasePhaseAngle(KSPActionParam param)
{
phaseAngle += stepAngle;
if (phaseAngle > maxAngle)
phaseAngle = maxAngle;
}
[KSPAction("Decrease Phase Angle")]
public void DecreasePhaseAngle(KSPActionParam param)
{
phaseAngle -= stepAngle;
if (phaseAngle < 0f)
phaseAngle = 0f;
}
private ModuleEngines engine;
private ModuleEnginesFX engineFX;
private ModuleEnginesRF engineRF;
private ModuleEnginesAJEJet engineAJE;
public override void OnStart(StartState state)
{
if (state == StartState.Editor)
return;
showMenu = false;
if (part.Modules.Contains("ModuleEngines"))
engine = (ModuleEngines)part.Modules["ModuleEngines"];
if (part.Modules.Contains("ModuleEnginesFX"))
engineFX = (ModuleEnginesFX)part.Modules["ModuleEnginesFX"];
if (part.Modules.Contains("ModuleEnginesRF"))
engineRF = (ModuleEnginesRF)part.Modules["ModuleEnginesRF"];
if (part.Modules.Contains("ModuleEnginesAJEJet"))
engineAJE = (ModuleEnginesAJEJet)part.Modules["ModuleEnginesAJEJet"];
}


public void FixedUpdate()
{
this.Fields["pitchNeutral"].guiActive = showMenu;
this.Fields["pitchNeutral"].guiActiveEditor = showMenu;
this.Fields["pitchRange"].guiActive = showMenu;
this.Fields["pitchRange"].guiActiveEditor = showMenu;
this.Fields["rollNeutral"].guiActive = showMenu;
this.Fields["rollNeutral"].guiActiveEditor = showMenu;
this.Fields["rollRange"].guiActive = showMenu;
this.Fields["rollRange"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActiveEditor = showMenu;
this.Fields["stepAngle"].guiActive = showMenu;
this.Fields["stepAngle"].guiActiveEditor = showMenu;


this.Fields["verticalspeed"].guiActive = showMenu;
this.Fields["verticalspeed"].guiActiveEditor = showMenu;


if (HighLogic.LoadedSceneIsEditor)
{

return;
}
if(HighLogic.LoadedSceneIsFlight && isEngaged)
{


float T = pitchNeutral;
T *= (1f - (float)vessel.verticalSpeed / verticalspeed);
T *= Mathf.Sin(phaseAngle / 57.259f);
T = Mathf.Clamp(T, 0f, 100f);
T += pitchRange * vessel.ctrlState.pitch;


float R = rollNeutral;
R *= (1f - (float)vessel.verticalSpeed / verticalspeed);
R *= Mathf.Sin(phaseAngle / 57.259f);
R = Mathf.Clamp(T, 0f, 100f);
R += pitchRange * vessel.ctrlState.roll;
float avgMoment = (T + R) / 2;
SetThrustPercentage(avgMoment);

}

}




void SetThrustPercentage(float avgMoment)
{


avgMoment = Mathf.Clamp(avgMoment, 0f, 100f);
if(engine!=null)
{
engine.thrustPercentage = avgMoment;
return;
}
if (engineFX != null)
{
engineFX.thrustPercentage = avgMoment;
return;
}
if (engineRF != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
if (engineAJE != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
}
}
}

Edited by Svm420
Link to comment
Share on other sites

I am trying to bring a unmaintained mod into 1.0.4 and add some new features to it, but I can't seem to get the menus to show up in game in the R click menu. Here is the code in question. It is a fork of the AVTOL mod. Thanks!


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using KSP;
using RealFuels;
using AJE;




namespace AVTOL
{
public class AVTOL:PartModule
{
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float pitchNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float pitchRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float rollNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float rollRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Phase Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float phaseAngle = 90f;

[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Max Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float maxAngle = 90f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Step Angle"),
UI_FloatRange(minValue = -90f, maxValue = 90f, stepIncrement = 0.5f)]
public float stepAngle = 22.5f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Vertical Cutoff"),
UI_FloatRange(minValue = 1f, maxValue = 100f, stepIncrement = 1f)]
public float verticalspeed = 100f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL setting:"),
UI_Toggle(disabledText = "Off", enabledText = "On")]
public bool showMenu = true;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL system:"),
UI_Toggle(disabledText = "Off", enabledText = "Engaged")]
public bool isEngaged = false;


[KSPAction("Toggle VTOL system")]
public void toggleSystem(KSPActionParam param)
{
isEngaged = !isEngaged;
print("VTOL Control System is " + (isEngaged ? "Engaged" : "Off"));
if(!isEngaged)
{
SetThrustPercentage(100f);
}
}
[KSPAction("Increase Phase Angle")]
public void increasePhaseAngle(KSPActionParam param)
{
phaseAngle += stepAngle;
if (phaseAngle > maxAngle)
phaseAngle = maxAngle;
}
[KSPAction("Decrease Phase Angle")]
public void DecreasePhaseAngle(KSPActionParam param)
{
phaseAngle -= stepAngle;
if (phaseAngle < 0f)
phaseAngle = 0f;
}
private ModuleEngines engine;
private ModuleEnginesFX engineFX;
private ModuleEnginesRF engineRF;
private ModuleEnginesAJEJet engineAJE;
public override void OnStart(StartState state)
{
if (state == StartState.Editor)
return;
showMenu = false;
if (part.Modules.Contains("ModuleEngines"))
engine = (ModuleEngines)part.Modules["ModuleEngines"];
if (part.Modules.Contains("ModuleEnginesFX"))
engineFX = (ModuleEnginesFX)part.Modules["ModuleEnginesFX"];
if (part.Modules.Contains("ModuleEnginesRF"))
engineRF = (ModuleEnginesRF)part.Modules["ModuleEnginesRF"];
if (part.Modules.Contains("ModuleEnginesAJEJet"))
engineAJE = (ModuleEnginesAJEJet)part.Modules["ModuleEnginesAJEJet"];
}


public void FixedUpdate()
{
this.Fields["pitchNeutral"].guiActive = showMenu;
this.Fields["pitchNeutral"].guiActiveEditor = showMenu;
this.Fields["pitchRange"].guiActive = showMenu;
this.Fields["pitchRange"].guiActiveEditor = showMenu;
this.Fields["rollNeutral"].guiActive = showMenu;
this.Fields["rollNeutral"].guiActiveEditor = showMenu;
this.Fields["rollRange"].guiActive = showMenu;
this.Fields["rollRange"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActiveEditor = showMenu;
this.Fields["stepAngle"].guiActive = showMenu;
this.Fields["stepAngle"].guiActiveEditor = showMenu;


this.Fields["verticalspeed"].guiActive = showMenu;
this.Fields["verticalspeed"].guiActiveEditor = showMenu;


if (HighLogic.LoadedSceneIsEditor)
{

return;
}
if(HighLogic.LoadedSceneIsFlight && isEngaged)
{


float T = pitchNeutral;
T *= (1f - (float)vessel.verticalSpeed / verticalspeed);
T *= Mathf.Sin(phaseAngle / 57.259f);
T = Mathf.Clamp(T, 0f, 100f);
T += pitchRange * vessel.ctrlState.pitch;


float R = rollNeutral;
R *= (1f - (float)vessel.verticalSpeed / verticalspeed);
R *= Mathf.Sin(phaseAngle / 57.259f);
R = Mathf.Clamp(T, 0f, 100f);
R += pitchRange * vessel.ctrlState.roll;
float avgMoment = (T + R) / 2;
SetThrustPercentage(avgMoment);

}

}




void SetThrustPercentage(float avgMoment)
{


avgMoment = Mathf.Clamp(avgMoment, 0f, 100f);
if(engine!=null)
{
engine.thrustPercentage = avgMoment;
return;
}
if (engineFX != null)
{
engineFX.thrustPercentage = avgMoment;
return;
}
if (engineRF != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
if (engineAJE != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
}
}
}

Although I am not near my PC right now, the code looks fine. So you have compiled this against the latest KSP assembly using .net 3.5

Have you been through the log to look for what errors you are getting?

Link to comment
Share on other sites

Hey everybody. I'm trying to build RemoteTech from source using monodevelop on linux. The remotetech code uses overloaded functions with default values. To my understanding this is a feature that's only available in .NET from 4.0 onwards. If I try to compile against .NET 4.0 I get an error, because Unity was built against .NET 3.5. So how do I go around doing this? How do the RT devs use default values?

Link to comment
Share on other sites

Hey everybody. I'm trying to build RemoteTech from source using monodevelop on linux. The remotetech code uses overloaded functions with default values. To my understanding this is a feature that's only available in .NET from 4.0 onwards. If I try to compile against .NET 4.0 I get an error, because Unity was built against .NET 3.5. So how do I go around doing this? How do the RT devs use default values?

I've used that feature plenty of times. It compiles fine in Visual Studio against .NET 3.5. Not sure about Monodevelop.

Link to comment
Share on other sites

Hey everybody. I'm trying to build RemoteTech from source using monodevelop on linux. The remotetech code uses overloaded functions with default values. To my understanding this is a feature that's only available in .NET from 4.0 onwards. If I try to compile against .NET 4.0 I get an error, because Unity was built against .NET 3.5. So how do I go around doing this? How do the RT devs use default values?

It should only be a problem if the default parameters result in two overloads using the same set of non-default parameters.

Something like this:


void funcOne (bool b, string s, bool c = false)
{

}

void funcOne (bool b, string s)
{

}

Even then I think it should compile, but the default parameter will just be pointless since it will only go to that function if you actually specify it. I'm also using VS, so maybe it's something specific to Monodevelop.

Link to comment
Share on other sites

Although I am not near my PC right now, the code looks fine. So you have compiled this against the latest KSP assembly using .net 3.5

Have you been through the log to look for what errors you are getting?

Well I am getting this error in my log. I was using .NET 3.5 and latest KSP


[ERR 13:40:07.129] AssemblyLoader: Exception loading 'AVTOL': System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
at System.Reflection.Assembly.GetTypes () [0x00000] in <filename unknown>:0
at AssemblyLoader.LoadAssemblies () [0x00000] in <filename unknown>:0

This is the source I was using when I got the error. I tried without the AJE and RF stuff and it works in the editor and shows up on all engines like it used to, but doesn't have any effect on engine thrust when pitching up or down like it should. That was on a RF engine so I can see I need to have them be a part of the plugin if I want it to work on that engine type.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using KSP;
using RealFuels;
using AJE;
using SolverEngines;




namespace AVTOL
{
public class AVTOL:PartModule
{
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float pitchNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float pitchRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Roll Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float rollNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Roll Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float rollRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Phase Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float phaseAngle = 90f;

[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Max Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float maxAngle = 90f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Step Angle"),
UI_FloatRange(minValue = -90f, maxValue = 90f, stepIncrement = 0.5f)]
public float stepAngle = 22.5f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Vertical Cutoff"),
UI_FloatRange(minValue = 1f, maxValue = 100f, stepIncrement = 1f)]
public float verticalspeed = 100f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL setting:"),
UI_Toggle(disabledText = "Off", enabledText = "On")]
public bool showMenu = true;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL system:"),
UI_Toggle(disabledText = "Off", enabledText = "Engaged")]
public bool isEngaged = false;


[KSPAction("Toggle VTOL system")]
public void toggleSystem(KSPActionParam param)
{
isEngaged = !isEngaged;
print("VTOL Control System is " + (isEngaged ? "Engaged" : "Off"));
if(!isEngaged)
{
SetThrustPercentage(100f);
}
}
[KSPAction("Increase Phase Angle")]
public void increasePhaseAngle(KSPActionParam param)
{
phaseAngle += stepAngle;
if (phaseAngle > maxAngle)
phaseAngle = maxAngle;
}
[KSPAction("Decrease Phase Angle")]
public void DecreasePhaseAngle(KSPActionParam param)
{
phaseAngle -= stepAngle;
if (phaseAngle < 0f)
phaseAngle = 0f;
}
private ModuleEngines engine;
private ModuleEnginesFX engineFX;
private ModuleEnginesRF engineRF;
private ModuleEnginesAJEJet engineAJEj;
private ModuleEnginesAJERotor engineAJEr;


public override void OnStart(StartState state)
{
if (state == StartState.Editor)
return;
showMenu = false;
if (part.Modules.Contains("ModuleEngines"))
engine = (ModuleEngines)part.Modules["ModuleEngines"];
if (part.Modules.Contains("ModuleEnginesFX"))
engineFX = (ModuleEnginesFX)part.Modules["ModuleEnginesFX"];
if (part.Modules.Contains("ModuleEnginesRF"))
engineRF = (ModuleEnginesRF)part.Modules["ModuleEnginesRF"];
if (part.Modules.Contains("ModuleEnginesAJEJet"))
engineAJEj = (ModuleEnginesAJEJet)part.Modules["ModuleEnginesAJEJet"];
if (part.Modules.Contains("ModuleEnginesAJERotor"))
engineAJEr = (ModuleEnginesAJERotor)part.Modules["ModuleEnginesAJERotor"];
}


public void FixedUpdate()
{
this.Fields["pitchNeutral"].guiActive = showMenu;
this.Fields["pitchNeutral"].guiActiveEditor = showMenu;
this.Fields["pitchRange"].guiActive = showMenu;
this.Fields["pitchRange"].guiActiveEditor = showMenu;
this.Fields["rollNeutral"].guiActive = showMenu;
this.Fields["rollNeutral"].guiActiveEditor = showMenu;
this.Fields["rollRange"].guiActive = showMenu;
this.Fields["rollRange"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActiveEditor = showMenu;
this.Fields["stepAngle"].guiActive = showMenu;
this.Fields["stepAngle"].guiActiveEditor = showMenu;
this.Fields["verticalspeed"].guiActive = showMenu;
this.Fields["verticalspeed"].guiActiveEditor = showMenu;


if (HighLogic.LoadedSceneIsEditor)
{

return;
}
if(HighLogic.LoadedSceneIsFlight && isEngaged)
{


float T = pitchNeutral;
T *= (1f - (float)vessel.verticalSpeed / verticalspeed);
T *= Mathf.Sin(phaseAngle / 57.259f);
T = Mathf.Clamp(T, 0f, 100f);
T += pitchRange * vessel.ctrlState.pitch;


float R = rollNeutral;
R *= (1f - (float)vessel.verticalSpeed / verticalspeed);
R *= Mathf.Sin(phaseAngle / 57.259f);
R = Mathf.Clamp(T, 0f, 100f);
R += rollRange * vessel.ctrlState.roll;
float avgMoment = (T + R) / 2;
SetThrustPercentage(avgMoment);

}

}




void SetThrustPercentage(float avgMoment)
{


avgMoment = Mathf.Clamp(avgMoment, 0f, 100f);
if(engine!=null)
{
engine.thrustPercentage = avgMoment;
return;
}
if (engineFX != null)
{
engineFX.thrustPercentage = avgMoment;
return;
}
if (engineRF != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
if (engineAJEj != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
if (engineAJEr != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
}
}
}

Link to comment
Share on other sites

Believe you are running into a race condition where your mod (starting with A) tries to load before RealFuels (letter R) or SolverEngines (letter S) and so when KSP processes your mod and tries to find the hooks into RealFuels and SolverEngines it can't as those mods have not yet loaded.

You can:

1) Change the name of your mod so it loads last.

-Older method that still works but is not the recommended way to do things any more.

2) Tag your mod with the KSPAssemblyDependency attributes for the mods you depend on. (I may have that command slightly wrong, it's from memory.)

-If your mod requires the mod you are linking to and will not work without it, this is the preferred way as it is easier to implement.

3) Change to using reflection for the interaction between mods.

-If your mod only uses the mod you are linking to as an option, this is the way you need to set things up to avoid having to release two versions of your mod, one version that uses the other mod, and a version that doesn't. It is more complex to setup however.

D.

Edited by Diazo
Link to comment
Share on other sites

Well I am getting this error in my log. I was using .NET 3.5 and latest KSP


[ERR 13:40:07.129] AssemblyLoader: Exception loading 'AVTOL': System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
at System.Reflection.Assembly.GetTypes () [0x00000] in <filename unknown>:0
at AssemblyLoader.LoadAssemblies () [0x00000] in <filename unknown>:0

This is the source I was using when I got the error. I tried without the AJE and RF stuff and it works in the editor and shows up on all engines like it used to, but doesn't have any effect on engine thrust when pitching up or down like it should. That was on a RF engine so I can see I need to have them be a part of the plugin if I want it to work on that engine type.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using KSP;
using RealFuels;
using AJE;
using SolverEngines;




namespace AVTOL
{
public class AVTOL:PartModule
{
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float pitchNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Pitch Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float pitchRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Roll Neutral%"),
UI_FloatRange(minValue = 0f, maxValue = 100f, stepIncrement = 1f)]
public float rollNeutral = 100f;
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Roll Range%"),
UI_FloatRange(minValue = -100f, maxValue = 100f, stepIncrement = 1f)]
public float rollRange = 0f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Phase Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float phaseAngle = 90f;

[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Max Angle"),
UI_FloatRange(minValue = 0f, maxValue = 180f, stepIncrement = 5f)]
public float maxAngle = 90f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Step Angle"),
UI_FloatRange(minValue = -90f, maxValue = 90f, stepIncrement = 0.5f)]
public float stepAngle = 22.5f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Vertical Cutoff"),
UI_FloatRange(minValue = 1f, maxValue = 100f, stepIncrement = 1f)]
public float verticalspeed = 100f;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL setting:"),
UI_Toggle(disabledText = "Off", enabledText = "On")]
public bool showMenu = true;


[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "VTOL system:"),
UI_Toggle(disabledText = "Off", enabledText = "Engaged")]
public bool isEngaged = false;


[KSPAction("Toggle VTOL system")]
public void toggleSystem(KSPActionParam param)
{
isEngaged = !isEngaged;
print("VTOL Control System is " + (isEngaged ? "Engaged" : "Off"));
if(!isEngaged)
{
SetThrustPercentage(100f);
}
}
[KSPAction("Increase Phase Angle")]
public void increasePhaseAngle(KSPActionParam param)
{
phaseAngle += stepAngle;
if (phaseAngle > maxAngle)
phaseAngle = maxAngle;
}
[KSPAction("Decrease Phase Angle")]
public void DecreasePhaseAngle(KSPActionParam param)
{
phaseAngle -= stepAngle;
if (phaseAngle < 0f)
phaseAngle = 0f;
}
private ModuleEngines engine;
private ModuleEnginesFX engineFX;
private ModuleEnginesRF engineRF;
private ModuleEnginesAJEJet engineAJEj;
private ModuleEnginesAJERotor engineAJEr;


public override void OnStart(StartState state)
{
if (state == StartState.Editor)
return;
showMenu = false;
if (part.Modules.Contains("ModuleEngines"))
engine = (ModuleEngines)part.Modules["ModuleEngines"];
if (part.Modules.Contains("ModuleEnginesFX"))
engineFX = (ModuleEnginesFX)part.Modules["ModuleEnginesFX"];
if (part.Modules.Contains("ModuleEnginesRF"))
engineRF = (ModuleEnginesRF)part.Modules["ModuleEnginesRF"];
if (part.Modules.Contains("ModuleEnginesAJEJet"))
engineAJEj = (ModuleEnginesAJEJet)part.Modules["ModuleEnginesAJEJet"];
if (part.Modules.Contains("ModuleEnginesAJERotor"))
engineAJEr = (ModuleEnginesAJERotor)part.Modules["ModuleEnginesAJERotor"];
}


public void FixedUpdate()
{
this.Fields["pitchNeutral"].guiActive = showMenu;
this.Fields["pitchNeutral"].guiActiveEditor = showMenu;
this.Fields["pitchRange"].guiActive = showMenu;
this.Fields["pitchRange"].guiActiveEditor = showMenu;
this.Fields["rollNeutral"].guiActive = showMenu;
this.Fields["rollNeutral"].guiActiveEditor = showMenu;
this.Fields["rollRange"].guiActive = showMenu;
this.Fields["rollRange"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActiveEditor = showMenu;
this.Fields["phaseAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActive = showMenu;
this.Fields["maxAngle"].guiActiveEditor = showMenu;
this.Fields["stepAngle"].guiActive = showMenu;
this.Fields["stepAngle"].guiActiveEditor = showMenu;
this.Fields["verticalspeed"].guiActive = showMenu;
this.Fields["verticalspeed"].guiActiveEditor = showMenu;


if (HighLogic.LoadedSceneIsEditor)
{

return;
}
if(HighLogic.LoadedSceneIsFlight && isEngaged)
{


float T = pitchNeutral;
T *= (1f - (float)vessel.verticalSpeed / verticalspeed);
T *= Mathf.Sin(phaseAngle / 57.259f);
T = Mathf.Clamp(T, 0f, 100f);
T += pitchRange * vessel.ctrlState.pitch;


float R = rollNeutral;
R *= (1f - (float)vessel.verticalSpeed / verticalspeed);
R *= Mathf.Sin(phaseAngle / 57.259f);
R = Mathf.Clamp(T, 0f, 100f);
R += rollRange * vessel.ctrlState.roll;
float avgMoment = (T + R) / 2;
SetThrustPercentage(avgMoment);

}

}




void SetThrustPercentage(float avgMoment)
{


avgMoment = Mathf.Clamp(avgMoment, 0f, 100f);
if(engine!=null)
{
engine.thrustPercentage = avgMoment;
return;
}
if (engineFX != null)
{
engineFX.thrustPercentage = avgMoment;
return;
}
if (engineRF != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
if (engineAJEj != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
if (engineAJEr != null)
{
engineRF.thrustPercentage = avgMoment;
return;
}
}
}
}

Well to me it looks like a .NET issue. Are all the DLLs you are referencing compiled against .Net 3.5? and the latest/same Assembly-CSharp (KSP)

IE: RealFuels, AJE, SolverEngines

EDIT: Ninja'd by Diazo. Like he said.

Link to comment
Share on other sites

Hello

I keep vessel specific notes (ascent details, action groups etc) in each of my vessel's descriptions and it would be useful to have that info shown in a window during flight instead of hastily-written-back-of-envelope notes cluttering my desk.

So I thought I'd spend 10 minutes making a quick plugin that shows the active vessel's description in flight.

Several hours later, I've got a window to show up and display the vessel's name. But nowhere in the API can I see how to retrieve its description. I rather think it may not be accessible. So my thought was, maybe I should read the description from the active vessel's .craft file directly.

So I have this as part of my code:

[font=Menlo][color=#444444]ShipConstruct[/color][color=#444444]ship[/color][color=#444444] = [/color][color=#009695]new[/color][color=#444444]ShipConstruct[/color][color=#444444] ();[/color][color=#444444]ship[/color][color=#444444].[/color][color=#444444]LoadShip[/color][color=#444444] ([/color][color=#444444]ConfigNode[/color][color=#444444].[/color][color=#444444]Load[/color][color=#444444] ([/color][color=#444444]FlightGlobals[/color][color=#444444].[/color][color=#444444]ActiveVessel[/color][color=#444444].[/color][color=#444444]vesselName[/color][color=#444444] + [/color][color=#f57c00]"[/color][color=#f57c00].craft[/color][color=#f57c00]"[/color][color=#444444]));[/color][color=#444444]vesselDescription[/color][color=#444444] = [/color][color=#444444]ship[/color][color=#444444].[/color][color=#444444]shipDescription[/color][color=#444444];[/color][/font]

Those three lines are what I've cobbled together after a few hours of hard Googling. However, the in-game debug reports the craft file is not found. Furthermore, I know this is bad as the craft filename is not necessarily going to be the actual craft's in-game name.

So, TL,DR;

Is reading directly from a .craft file the best way to retrieve a vessel's description?

If so, how do I get the active vessel's filename (and full game path if I have to pass an absolute path instead of a relative one) ?

Or is there a description property hiding in the API somewhere I can just grab?

Any help would be much appreciated!

Dave

Link to comment
Share on other sites

Welcome to one of the holes in the current setup we have to work with.

The core issue is that when KSP parses the .craft file to make the in-flight vessel, it does not bring across the description text for some reason so it is simply not there to be found on a spawned vessel in flight.

So yes, the only way to see the description in flight is to read the .craft file.

However, as you noted the .craft file is the vessel name, if you rename the vessel you no longer have any way of linking the in-flight vessel back to the .craft file to find the description.

I've struggled with this extensively for my AGX mod and there is no real good answer.

To answer your questions however, the reason that the .craft file can not be found is because you did not give it a file path so KSP is looking for it in the KSP directory, not the game save directory.

I load a .cfg file from the root save directory with this code, you should be able to extend it easily enough to load from the ships sub-folder at that location.

However, it might be simpler to tack on a partModule of your own to same a second copy of the notes in the editor that you can load in flight.

Also, I'm pretty sure I've seen a couple other mods that do this although I can't remember their exact names at the moment if you are willing to go that route. (In-flight notes, notepad? something like that.)

D.

Link to comment
Share on other sites

Hello

I keep vessel specific notes (ascent details, action groups etc) in each of my vessel's descriptions and it would be useful to have that info shown in a window during flight instead of hastily-written-back-of-envelope notes cluttering my desk.

So I thought I'd spend 10 minutes making a quick plugin that shows the active vessel's description in flight.

Several hours later, I've got a window to show up and display the vessel's name. But nowhere in the API can I see how to retrieve its description. I rather think it may not be accessible. So my thought was, maybe I should read the description from the active vessel's .craft file directly.

So I have this as part of my code:

[FONT=Menlo][COLOR=#444444]
ShipConstruct[/COLOR][COLOR=#444444]ship[/COLOR][COLOR=#444444] = [/COLOR][COLOR=#009695]new[/COLOR][COLOR=#444444]ShipConstruct[/COLOR][COLOR=#444444] ();[/COLOR]
[COLOR=#444444]ship[/COLOR][COLOR=#444444].[/COLOR][COLOR=#444444]LoadShip[/COLOR][COLOR=#444444] ([/COLOR][COLOR=#444444]ConfigNode[/COLOR][COLOR=#444444].[/COLOR][COLOR=#444444]Load[/COLOR][COLOR=#444444] ([/COLOR][COLOR=#444444]FlightGlobals[/COLOR][COLOR=#444444].[/COLOR][COLOR=#444444]ActiveVessel[/COLOR][COLOR=#444444].[/COLOR][COLOR=#444444]vesselName[/COLOR][COLOR=#444444] + [/COLOR][COLOR=#f57c00]"[/COLOR][COLOR=#f57c00].craft[/COLOR][COLOR=#f57c00]"[/COLOR][COLOR=#444444]));[/COLOR]
[COLOR=#444444]vesselDescription[/COLOR][COLOR=#444444] = [/COLOR][COLOR=#444444]ship[/COLOR][COLOR=#444444].[/COLOR][COLOR=#444444]shipDescription[/COLOR][COLOR=#444444];
[/COLOR][/FONT]

Those three lines are what I've cobbled together after a few hours of hard Googling. However, the in-game debug reports the craft file is not found. Furthermore, I know this is bad as the craft filename is not necessarily going to be the actual craft's in-game name.

So, TL,DR;

Is reading directly from a .craft file the best way to retrieve a vessel's description?

If so, how do I get the active vessel's filename (and full game path if I have to pass an absolute path instead of a relative one) ?

Or is there a description property hiding in the API somewhere I can just grab?

Any help would be much appreciated!

Dave

Firespitter has a PartModule that gives you info when you press a particular button - the module name is FSinfoPopup. It's used in B9.

Link to comment
Share on other sites

Question. Would the following code be the correct way to open and close intakes based on altitude? It appears to work, I'm just a total noob at this so just checking to make sure. Thanks.

        //Close Intakes
if (FlightGlobals.ActiveVessel.altitude < 1.0)
{
foreach (ModuleResourceIntake s in FlightGlobals.ActiveVessel.FindPartModulesImplementing<ModuleResourceIntake>())
{
s.Deactivate();
intakesClosed = true;
}
}
else
{
if (intakesClosed)
{
foreach (ModuleResourceIntake s in FlightGlobals.ActiveVessel.FindPartModulesImplementing<ModuleResourceIntake>())
{
s.Activate();
intakesClosed = false;
}
}
}
//end Close Intakes

And another question. If I wanted to change the thrust on any engine on the vessel based on altitude, would I need to do something like this to both ModuleEngines AND ModuleEnginesFX or is there a way to get all engines at once? Basically, for this one, I'm trying to keep my boats from flying.

Edited by Fengist
Link to comment
Share on other sites

hello! i am new to KSP modding and i have taken quite a daunting task on my first project... on-the-fly part welding. now i have most of the parts done for(testing still due on some things but it seems to be good) but i have gotten into quite of a problem with resources

  partConfig.Save(KSPUtil.ApplicationRootPath+ "\\EladsConfig.cfg");            Part FinalPart = ConfigNode.CreateObjectFromConfig<Part>(partConfig) ;
//ConfigNode.LoadObjectFromConfig(FinalPart, partConfig);
List<PartResource> newList = new List<PartResource>();
foreach (ConfigNode node in TotalResources)
{
Debug.Log(" creating resources ");
PartResource res = new PartResource();
string resourceName = node.GetValue("name");
double resourceAmount = double.Parse(node.GetValue("amount"));
double resourceMax = double.Parse(node.GetValue("maxAmount"));
res.resourceName = resourceName;
res.amount = resourceAmount;
res.maxAmount = resourceMax;
FinalPart.Resources.Add(node);


}
Debug.Log(" created resources ");
Debug.Log(" Created Part ");
Debug.Log(" Part mass " + FinalPart.mass);
Debug.Log(" Part Name " + FinalPart.partName);
return FinalPart;

everytime i use FinalPart.Resources or try to access it i get a Null-reference-exception and when i check i see it's null but i cant add to it anything. Yes the Config Node is perfect i checked it against other stock parts. other then rerouting the part through a copy of another one i am lost

Link to comment
Share on other sites

Fengist:

1. The code looks correct, although it's worth noting that in Unity, foreach is a bad idea in realtime applications. I'd suggest something like:


if(FlightGlobals.ActiveVessel != null)
for(int p = FlightGlobals.ActiveVessel.Parts.Count - 1; p >= 0; --p)
{
for(int i = FlightGlobals.ActiveVessel.Parts[p].Modules.Count - 1; i >= 0; --i)
{
PartModule m = FlightGlobals.ActiveVessel.Parts[p].Modules[i];
if(m is ModuleResourceIntake)
(m as ModuleResourceIntake).Activate()
}
}

2. ModuleEnginesFX derives from ModuleEngines. So you can just use the above code, and instead of checking if m is ModuleResourceIntake (and casting to that) you can check if m is ModuleEngines and cast to that.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...