Jump to content

ConfigNode - Brain is not cooperating...


Recommended Posts

First, a little background info:

So, a while back a plugin was released by Pizzaoverhead (I sure hope I didn't butcher that) called CollisionFX. This plugin creates sparks and dust plumes to coincide with collisions between the active vessel and... well... everything else. There were some limitations, however. One of those was related to wheels. When rolling over anything not specifically classified as dirt, such as the false landscape that acts as the foundation of the KSC compound, the wheel would throw sparks and dust and lights and all sorts of crazy stuff as you rolled happily along. This was solved by disabling the effect for wheels.

However, there was one part of those effects that were rather nice for the wheel: the dust. Over at the Kerbal Foundries development thread we discovered just how perfect the dust fit in with lo-fi's wheels and, more specifically, the tracks he developed. The sparks had to go, though. So, as a completely inexperienced programmer, I thought to myself "how hard could it be?" and dove right in to try and adapt the code to fit our needs. I had a number of issues while I worked on the original part module "CollisionFX" where i was attempting to separate the setup for the sparks from the dust. After a number of tries that ended up breaking the entire functionality of the plugin, I decided it was time to revert everything I had done and try to extract only the parts that I needed into a new class. This was a complete success and soon I was spawning dust in the wake of my rovers everywhere, complete with planetary and biome specific settings for dust color.

Warping up about a month and now I have almost every setting that controls the dust strength, minimal and maximal particle counts, etc. running from fields which can be customized in the part module parameters. I've even broken free from the original DLL (just yesterday in fact) and have practically rewritten the entire thing in the process. Now I want to take it a step further: configuration files.

The problems begin:

This is where the headache begins. I know there are many plugins that I use in KSP that read/write to the scenarios in the persistence file, and countless others that read/write to their own configuration files. Almost all of these are sitting on my hard drive in full source, and I've been pouring over them to try and figure out how to adapt them to my needs. I want to load up the definitions for the planetary and biome specific dust colors from a config file so that these definitions can be expanded without having to recompile the entire thing. Right now they are all hard-coded and called up like this:

[COLOR=#0000ff][B]
public[/B][/COLOR] [COLOR=#ff0000]string[/COLOR] [COLOR=#191970][B]GetCurrentBiomeName[/B][/COLOR] ()
{
[COLOR=#004085]CBAttributeMapSO[/COLOR] biomeMap = [COLOR=#004085]FlightGlobals[/COLOR].[I]currentMainBody[/I].[I]BiomeMap[/I];
[COLOR=#004085]CBAttributeMapSO[/COLOR].[COLOR=#004085]MapAttribute[/COLOR] mapAttribute = biomeMap.[COLOR=#191970][B]GetAtt[/B][/COLOR](vessel.[I]latitude[/I] * [COLOR=#004085][B]Mathf[/B][/COLOR].[I]Deg2Rad[/I], vessel.[I]longitude[/I] * [COLOR=#004085][B]Mathf[/B][/COLOR].[I]Deg2Rad[/I]);
[COLOR=#000080]return[/COLOR] mapAttribute.[I]name[/I];
}

[COLOR=#008000]// Color format: RGBA (0-1, decimal percentage)[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]genericDustColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.75[/COLOR]f, [COLOR=#00008b]0.75[/COLOR]f, [COLOR=#00008b]0.75[/COLOR]f, [COLOR=#00008b]0.007[/COLOR]f);
[COLOR=#008000]// Grey 210 210 210[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]dirtColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.65[/COLOR]f, [COLOR=#00008b]0.48[/COLOR]f, [COLOR=#00008b]0.34[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Brown 165, 122, 88[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]lightDirtColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.65[/COLOR]f, [COLOR=#00008b]0.52[/COLOR]f, [COLOR=#00008b]0.34[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Brown 165, 132, 88[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]sandColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.80[/COLOR]f, [COLOR=#00008b]0.68[/COLOR]f, [COLOR=#00008b]0.47[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Light brown 203, 173, 119[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]snowColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.90[/COLOR]f, [COLOR=#00008b]0.94[/COLOR]f, [COLOR=#00008b]1[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Blue-white 230, 250, 255[/COLOR]

[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [COLOR=#191970][B]GetBiomeColour[/B][/COLOR] ( [COLOR=#004085]Collider[/COLOR] c )
{
[COLOR=#0000ff][B]switch[/B][/COLOR] ([COLOR=#004085]FlightGlobals[/COLOR].ActiveVessel.mainBody.name)
{
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Kerbin"[/COLOR]:
[COLOR=#0000ff][B]if[/B][/COLOR] ([COLOR=#191970][B]IsPQS[/B][/COLOR](c))
{
[COLOR=#ff0000]string[/COLOR] biome = [COLOR=#191970][B]GetCurrentBiomeName[/B][/COLOR]();
[COLOR=#0000ff][B]switch[/B][/COLOR] (biome)
{
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Water"[/COLOR]: [COLOR=#008000]//Anything here would be the sea-bottom.[/COLOR]
[COLOR=#000080]return[/COLOR] [I]lightDirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Grasslands"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Highlands"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Shores"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]lightDirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Mountains"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Deserts"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]sandColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Badlands"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Tundra"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Ice Caps"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]snowColour[/I];
[COLOR=#0000ff][B]default[/B][/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
}
}
[COLOR=#000080]return[/COLOR] [I]genericDustColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Duna"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]sandColour[/I];
[COLOR=#0000ff][B]default[/B][/COLOR]:
[COLOR=#000080]return[/COLOR] [I]genericDustColour[/I];
}
}

This is one area where the code is almost completely identical to what CollisionFX uses. At this time, to expand this further you'd have to edit that switch right there and add more cases. What I would like to do is instead make it load those definitions from a two-layered config node system such as, for example:

BODY
{
name = Kerbin
//Color format: (decimal) red, green, blue, alpha
color = 0.75, 0.75, 0.75, 0.007
BIOME
{
name = Ice Caps
color = 0.90, 0.94, 1, 0.0125
}
BIOME
{
name = Highlands
color = 0.65, 0.48, 0.34, 0.0125
}
}
BODY
{
name = Duna
color = 0.80, 0.68, 0.47, 0.0125
}

Now, I'm unsure why this is causing me such a headache, but every time I try to adapt some new way of coding the retrieval and use of settings from a file formatted in such a way I hit this brick wall in my ability to comprehend where and what needs to happen to make it all fit in the right place. I haven't even made it as far as actually telling the GetBiomeColour() method how to read the new data because I get this pain in the head every time I try to write the code that will import the configuration data. I don't really believe it's that complicated, but I can't seem to wrap my head around it. Sorta like statistics class... I had to drop that one this quarter due to just not being able to make sense of it.

Obviously I don't lack examples of this being done, but what I do lack is a clear idea of what is happening and why it works in the code I am looking at. I have been taking a C# beginners class in college, preparing for a BA program in Application Development (it's a really vague description, and I'm not sure what it really means yet, but I'm having a blast getting ready for it.) and from what I've learned there, combined with my dabbling in these more advanced things that we do for KSP, I have a basic idea of what I'd like to have happen here. First, I would define the file that I'm loading from (path to locate it relative to the plugin, or absolute if I had to) and then I would define the node names I need to look for. I would then, much like I would do in a class example, create something along the lines of a two-dimensional array that would contain the body names in the first dimension, and the biome names in the second one. This is where the first painful spasm comes about as I think to myself "wait a sec, you dummy... the only planet that we have any clue about as far as biomes that correspond to landscape regions is Kerbin, so having biome info for other worlds is kinda stupid, aint it?" and I generally start to have a miniature stoke. Upon recovering from that, I continue. Okay, so maybe we leave Kerbin and it's biomes alone for now and concentrate on just expanding the planetary color definitions.

So, I scrap the subnodes for "BIOME" in the proverbial trash bin and continue. we have now a pretty simple array that will contain the names of all the planets and a default setting for their dust colors. Another little painful twinge hits me as I say to myself "wait a second, my professor tells me that defining a new array without any clue how large it will be in the end is a recipe for disaster and that he will come back from the grave and haunt me if I do it... so that's not going to work very well" and another miniature stoke hits me.

So, at this point I normally give up, scrap everything having to do with config nodes and go play a mindless zombie killing game. I'm really looking for some configuration-for-dummies style direction here. My brain can't take these miniature strokes forever, though they're beginning to feel a little bit like a sweet moment of release and I get a really weird craving for chocolate chip cookies... am I going totally nuts? Probably... I'll ask the dancing midget in the corner next time I get a chance.

Edited by Gaalidas
I'm a typo machine.
Link to comment
Share on other sites

Loading configs

It's easier to load confignodes through GameDatabase IMO (the class which holds everything KSP loads on start), instead of by a certain file.

GameDatabase.Instance.GetConfigNodes(NodeName) returns a list of confignodes of type NodeName

eg.

List<Confignode> nodes = GameDatabase.Instance.GetConfigNodes("BODY"); // Contains all the BODY type config nodes

From there, I would have a "Body" class/struct for data storage of each "Body" config node. Body class would store the name, Colour, and a list (maybe, see bottom of post) of Biomes

foreach (Confignode node in nodes)
{
BodyList.Add(new Body(node));
}

The constructor for the Body class would take a config node and operate on it like so...


bodyName = node.GetValue("name");
string[] tempString = node.GetValue("colour").split(','); // colour conversion should really be a function you can call.
float[] colVals = new float[4];
for (int i = 0; i < 4; i++)
{
float.TryParse(tempString[i].Trim(), out colVals[i]);
}
bodyColour = new Colour(colVals[0],colVals[1],...);

foreach(ConfigNode biomeNode in node.GetNodes("Biome"))
BiomeList.Add(new Biome(biomeNode)); // if biome is only ever going to be a name and a colour, just make a dictionary of that rather than another class
...

Filter Extensions uses this very approach. Trace through the Subcategory => Filter => Check constructors in here for a working example (originates here)

Summary

GameDatabase.Instance.GetConfigNodes("nodeType") is a nice loading method. Returns a list of configNodes

node.GetValue("key") give you the value after the equals sign in a key/value pair (key = value) as a string.

node.GetNodes("nodeType") gets you a list of child configNodes of a certain type (eg. BIOME)

Retrieving Data

You probably want to consider whether to use a Dictionary or List for storing the Bodies and Biomes. I've used a list here out of habit, but if you want to look up the values for Biome x on Body y, storing them as a Dictionary makes more sense (dictionaries are just lookup tables which means access to a specific value is much faster than a list).

Dictionary<string, Body> BodyDict = new Dictionary<string, Body>(); // Stores body classes with a string lookup identifier
if (!BodyDict.ContainsKey("Kerbin")) // always check to see if a dictionary actually has the key you want to access or add (Dictionaries don't like duplicate keys and a key that can't be found is as good as an out of bouds array index)
BodyDict.Add("Kerbin", new Body("KerbinNode"));
else
Debug.Log("bodyDict already contains key: " + "Kerbin"); // logging when an escape clause is fired.

if (BodyDict.ContainsKey("Kerbin"))
{
Body kerb = BodyDict["Kerbin"]; // retrieving the Body object with "Kerbin" as it's key
// if body stores biomes in a similar Dictionary
if (body.biomes.ContainsKey("desert"))
Biome desert = kerb.biomes["desert"]; // retrieveing kerbins desert Biome object
else
Debug.Log("biomeDict doesn't contain key: " + "desert");
}
else
Debug.Log("No key in bodyDict: " + "Kerbin");

My rule of thumb for when to use Arrays/Dictionaries/Lists is that: Arrays are for groups of data of fixed size that will be accessed by index, Lists are for data I need to iterate over (or for when I need an array of variable size), Dictionaries are for accessing data by a non-numeric or non-continuous id (planet or biome name in this case). Appropriate choice of storage type makes everything else much easier.

Edited by Crzyrndm
forgot instance in gamedatabase
Link to comment
Share on other sites

If you need a more practicle example of that, you might want to look at RealChute

For example, parachute materials are all being loaded via config node. The mod sweeps the GameDatabase looking for all MATERIAL nodes, and then keeps those to store them into custom objects.

Here's both classes who direct the loading and storage of that data. I use both a dictionary and an array as storage structures because this way I get easy lookup both by material name and by index. As for the node.TryGetValue() methods, they are ConfigNode extensions from my own. Feel free to use them if you want to.

Link to comment
Share on other sites

Sweet. My head is feeling better already. Now if I could just get the dancing midget to move on... you know how they tend to creep in and never go away...

EDIT: One thing I noticed in your code is that SharpDevelop (the program I use to do this stuff) is flagging this:

[COLOR=#008000][COLOR=#808080]///[/COLOR] [COLOR=#808080]<[B]summary[/B]>[/COLOR][/COLOR]
[COLOR=#008000][COLOR=#808080]///[/COLOR] Gets the index of the material looked for[/COLOR]
[COLOR=#008000][COLOR=#808080]///[/COLOR] [COLOR=#808080]<[B]/[/B][B]summary[/B]>[/COLOR][/COLOR]
[COLOR=#008000][COLOR=#808080]///[/COLOR] [COLOR=#808080]<[B]param[/B] [B]name[/B][B]=[/B][COLOR=#c0c0c0][B]"name"[/B][/COLOR]>[/COLOR]Name of the material[COLOR=#808080]<[B]/[/B][B]param[/B]>[/COLOR][/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#ff0000][B]int[/B][/COLOR] [COLOR=#191970][B]GetMaterialIndex[/B][/COLOR] ( [COLOR=#ff0000]string[/COLOR] name )
{
[COLOR=#000080] return[/COLOR] [I]_materialNames[/I].[COLOR=#191970][B]IndexOf[/B][/COLOR](name);
}

...the item "name" in the "_materialNames.IndexOf()" is being flagged as "Cannot implicitly convert type 'string' to '?[]'"

Other than that, this code is (as my C# professor Suzuki would say) "beautiful code."

EDIT2: Odd, when I loaded up the complete RealChute source, the flag does not come up in that same spot. Oh well.

Edited by Gaalidas
Link to comment
Share on other sites

Gotcha. I've got the same bug, I just lack the expertise to do it myself.

Actually, what really has me messed up is that I can't write some code, make it output the result to the console and run it immediately like I would in the C# class, where we're only creating console applications. It would be really nice if there was some sort of development console we could run our code into and get some dummy results that would help make sense of it all. KSP takes over 10 minutes to launch even with a near-empty GameData folder, so that's not really very useful to me.

Edited by Gaalidas
Link to comment
Share on other sites

no no no, by "bug" I meant, the perfectionism thing.

Now I've got images of the original "bug" which brought about the term in relation to computers stuck in my head. I've gotta go see that exhibit next time they bring it up from storage.

Link to comment
Share on other sites

What I would like to do is instead make it load those definitions from a two-layered config node system such as, for example:
BODY
{
name = Kerbin
//Color format: (decimal) red, green, blue, alpha
color = 0.75, 0.75, 0.75, 0.007
BIOME
{
name = Ice Caps
color = 0.90, 0.94, 1, 0.0125
}[/snip]

Now, I'm unsure why this is causing me such a headache, but every time I try to adapt some new way of coding the retrieval and use of settings from a file formatted in such a way I hit this brick wall in my ability to comprehend where and what needs to happen to make it all fit in the right place.

There are some ConfigNode tricks you can use to make this really simple. I don't know if you still intend to use the above format, but I'll use it as an example. Break the problem down. First, you need some kind of biome color description:

    public class BiomeDustColorInfo
{
[Persistent]
public string Name;

[Persistent]
public Color Color = Color.clear;
}

The [Persistent] tag will let KSP know it should set these values for us. This will be important in a bit. Next, we have some kind of planet description:

    public class BodyDustColorInfo : IPersistenceLoad
{
[Persistent]
public string Name;

[Persistent]
public Color DefaultColor = Color.clear;

[Persistent]
public List<BiomeDustColorInfo> BiomeColors = new List<BiomeDustColorInfo>();

private Dictionary<string, Color> _colorDictionary = new Dictionary<string, Color>();

public void PersistenceLoad()
{
_colorDictionary = BiomeColors.ToDictionary(ci => ci.Name, ci => ci.Color);
}

public Color GetDustColor(string name)
{
Color color;

return _colorDictionary.TryGetValue(name, out color) ? color : DefaultColor;
}
}

This one is a bit fancier. You'll notice we're also going to have KSP serialize a list for us. It's the only array-type object KSP's ConfigNode serialization method works on as far as I know. Of course, a list isn't very fast. We'd really like to have that data stored in a dictionary. That's where IPersistenceLoad comes in. Right after ConfigNode deserializes this object, it will call PersistenceLoad and we can do our transformation there.

Now, presumably we have some object we'll query later for dust color. That might look like this:


public class DustColorDefinitions : IPersistenceLoad, IPersistenceSave
{
[Persistent] private List<BodyDustColorInfo> BodyDustColors = new List<BodyDustColorInfo>();
[Persistent] private Color DefaultColor = Color.clear;

private Dictionary<CelestialBody,
BodyDustColorInfo>
_dustColors = new Dictionary<CelestialBody, BodyDustColorInfo>();


public Color GetDustColor(CelestialBody body, double lat, double lon)
{
BodyDustColorInfo biomeColors;
BiomeDustColorInfo dustColor;

if (!_dustColors.TryGetValue(body, out biomeColors))
return DefaultColor;

var biome = FlightGlobals.ActiveVessel == null
? string.Empty
: (string.IsNullOrEmpty(FlightGlobals.ActiveVessel.landedAt)
? ScienceUtil.GetExperimentBiome(body, lat, lon)
: Vessel.GetLandedAtString(FlightGlobals.ActiveVessel.landedAt));

return biomeColors.GetDustColor(biome);
}


public void PersistenceLoad()
{
_dustColors = BodyDustColors
.Where(info => FlightGlobals.Bodies.Any(b => b.bodyName == info.Name))
.ToDictionary(
info => FlightGlobals.Bodies.Single(b => b.bodyName == info.Name), c => c);
}


public void PersistenceSave()
{
if (!BodyDustColors.Any())
{
// generate default config
BodyDustColors = FlightGlobals.Bodies.Where(cb => cb.BiomeMap != null).Select(b => new BodyDustColorInfo
{
DefaultColor = this.DefaultColor,
Name = b.bodyName,
BiomeColors = b.BiomeMap.Attributes
.GroupBy(attr => attr.name)
.Select(group => group.First())
.Select(attr => new BiomeDustColorInfo {Color = attr.mapColor, Name = attr.name}).ToList()
}).ToList();
}
}
}

You'll notice this is the same idea as the previous class except that we've added IPersistenceSave. That gets called right before ConfigNode serializes this object. I took advantage of this to build a default ConfigNode to make editing a little easier.

Now, at this point the persistent tags and IPersistences don't actually do anything. Here's where the magic happens:

    public class SomeAddonOrScenarioModuleOrWhatever : MonoBehaviour
{
private DustColorDefinitions dustDefinitions = new DustColorDefinitions();

private void Awake()
{

// save default config
// ConfigNode.Save sometimes strips out the root node which could be a problem if it's empty,
// leading to a blank cfg = crashes KSP loader
var defaultConfig = ConfigNode.CreateConfigFromObject(dustDefinitions);
defaultConfig.name = "DustColorDefinitions";

System.IO.File.WriteAllText(KSPUtil.ApplicationRootPath + "GameData/DustColorDefinitions.cfg", defaultConfig.ToString());


var definition = GameDatabase.Instance.GetConfigNodes("DustColorDefinitions").Single();

if (!ConfigNode.LoadObjectFromConfig(dustDefinitions, definition))
print("ERROR: failed to load dust definitions");
}


private void Update()
{
print("Current dust color: " +
dustDefinitions.GetDustColor(FlightGlobals.ActiveVessel.mainBody,
FlightGlobals.ActiveVessel.latitude, FlightGlobals.ActiveVessel.longitude));

}
}

(The default config generated will look like the following)


{
DefaultColor = 0,0,0,0
BodyDustColors
{
Item
{
Name = Kerbin
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Water
Color = 0,0.1960784,0.5176471,1
}
Item
{
Name = Grasslands
Color = 0.3490196,0.7843137,0.05882353,1
}
Item
{
Name = Highlands
Color = 0.1098039,0.5333334,0,1
}
Item
{
Name = Shores
Color = 0.7058824,0.3882353,0.5176471,1
}
Item
{
Name = Mountains
Color = 0.509804,0.2745098,0,1
}
Item
{
Name = Deserts
Color = 0.9607843,0.7372549,0,1
}
Item
{
Name = Badlands
Color = 0.02745098,0.1490196,0.03529412,1
}
Item
{
Name = Tundra
Color = 0.4705882,0.8862745,0.4,1
}
Item
{
Name = Ice Caps
Color = 0.9960784,0.9960784,0.9960784,1
}
}
}
Item
{
Name = Mun
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Midlands
Color = 0.4392157,0.4392157,0.4392157,1
}
Item
{
Name = Northern Basin
Color = 0.3882353,0.01176471,0.3960784,1
}
Item
{
Name = East Crater
Color = 0,0.9960784,0.3294118,1
}
Item
{
Name = Northwest Crater
Color = 0.6941177,0.427451,0.1137255,1
}
Item
{
Name = Southwest Crater
Color = 0.772549,0.9960784,0,1
}
Item
{
Name = Farside Crater
Color = 0.9843137,0,0.9960784,1
}
Item
{
Name = Canyons
Color = 0.6627451,0.6235294,0,1
}
Item
{
Name = Polar Crater
Color = 0.9960784,0,0,1
}
Item
{
Name = Poles
Color = 0.4,0.9764706,0.9960784,1
}
Item
{
Name = Polar Lowlands
Color = 0.3215686,0.7803922,0.7960784,1
}
Item
{
Name = Highlands
Color = 0.9960784,0.9960784,0.9960784,1
}
Item
{
Name = Highland Craters
Color = 0.6784314,0.3843137,0.7333333,1
}
Item
{
Name = Midland Craters
Color = 0.1058824,0.1058824,0.1058824,1
}
Item
{
Name = East Farside Crater
Color = 0.1176471,0.007843138,1,1
}
Item
{
Name = Twin Craters
Color = 1,0.5647059,0,1
}
}
}
Item
{
Name = Minmus
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Highlands
Color = 0.254902,0.2941177,0.254902,1
}
Item
{
Name = Midlands
Color = 0.5215687,0.7176471,0.6392157,1
}
Item
{
Name = Lowlands
Color = 0.7372549,0.8941177,0.7568628,1
}
Item
{
Name = Flats
Color = 0.1960784,0.2745098,0.3529412,1
}
Item
{
Name = Great Flats
Color = 0.3411765,0.5450981,0,1
}
Item
{
Name = Greater Flats
Color = 0.3529412,0.1372549,0.4156863,1
}
Item
{
Name = Lesser Flats
Color = 0.9960784,0,0,1
}
Item
{
Name = Poles
Color = 0,0.3529412,0.9960784,1
}
Item
{
Name = Slopes
Color = 0.572549,0.3490196,0.3921569,1
}
}
}
Item
{
Name = Moho
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = North Pole
Color = 1,0.682353,0,1
}
Item
{
Name = Northern Sinkhole Ridge
Color = 1,0,0.4705882,1
}
Item
{
Name = Northern Sinkhole
Color = 1,0.9176471,0,1
}
Item
{
Name = Midlands
Color = 0.3882353,0.2627451,0.07843138,1
}
Item
{
Name = Western Lowlands
Color = 1,0,0,1
}
Item
{
Name = Central Lowlands
Color = 0,1,0.04705882,1
}
Item
{
Name = Highlands
Color = 0.1372549,0.3921569,0.1686275,1
}
Item
{
Name = Minor Craters
Color = 0.4980392,0.7058824,0,1
}
Item
{
Name = South Western Lowlands
Color = 0,1,0.9411765,1
}
Item
{
Name = South Eastern Lowlands
Color = 0.04705882,0,1,1
}
Item
{
Name = Canyon
Color = 0.9764706,0.6392157,0.6392157,1
}
Item
{
Name = South Pole
Color = 0.9882353,0,1,1
}
}
}
Item
{
Name = Eve
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Poles
Color = 0.9882353,1,0,1
}
Item
{
Name = Midlands
Color = 0,0.8941177,1,1
}
Item
{
Name = Explodium Sea
Color = 0.1176471,0,1,1
}
Item
{
Name = Lowlands
Color = 0,1,0.1411765,1
}
Item
{
Name = Highlands
Color = 1,0,0,1
}
Item
{
Name = Peaks
Color = 1,0.6352941,0,1
}
Item
{
Name = Impact Ejecta
Color = 0.6862745,0.7176471,0.3137255,1
}
}
}
Item
{
Name = Duna
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Poles
Color = 1,0,0,1
}
Item
{
Name = Midlands
Color = 0,1,0.1647059,1
}
Item
{
Name = Lowlands
Color = 0,0.1882353,1,1
}
Item
{
Name = Craters
Color = 0.682353,0,1,1
}
Item
{
Name = Highlands
Color = 0,0.9647059,1,1
}
}
}
Item
{
Name = Ike
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Polar Lowlands
Color = 0,0.9882353,1,1
}
Item
{
Name = Midlands
Color = 0.6588235,0,1,1
}
Item
{
Name = Eastern Mountain Ridge
Color = 1,0.02352941,0,1
}
Item
{
Name = Western Mountain Ridge
Color = 1,0.5176471,0,1
}
Item
{
Name = Lowlands
Color = 0.9647059,1,0,1
}
Item
{
Name = South Eastern Mountain Range
Color = 1,0,0.8941177,1
}
Item
{
Name = South Pole
Color = 0.4705882,1,0,1
}
Item
{
Name = Central Mountain Range
Color = 0.09411765,0,1,1
}
}
}
Item
{
Name = Laythe
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Poles
Color = 0,0.9882353,1,1
}
Item
{
Name = Shores
Color = 0.9921569,0.6784314,0.007843138,1
}
Item
{
Name = Dunes
Color = 0.02352941,1,0,1
}
Item
{
Name = Crescent Bay
Color = 1,0,0,1
}
Item
{
Name = The Sagen Sea
Color = 0.02352941,0.1529412,0.9764706,1
}
}
}
Item
{
Name = Vall
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Poles
Color = 1,0,0,1
}
Item
{
Name = Midlands
Color = 0.9843137,0.01568628,0.4823529,1
}
Item
{
Name = Highlands
Color = 0,0.1882353,1,1
}
Item
{
Name = Lowlands
Color = 0,1,0.02352941,1
}
}
}
Item
{
Name = Bop
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Peaks
Color = 0,0.9176471,1,1
}
Item
{
Name = Ridges
Color = 0.4745098,0.4823529,1,1
}
Item
{
Name = Poles
Color = 1,0.6117647,0,1
}
Item
{
Name = Slopes
Color = 1,0,0.7529412,1
}
Item
{
Name = Valley
Color = 0.9882353,1,0,1
}
}
}
Item
{
Name = Tylo
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Midlands
Color = 0.9960784,0.003921569,0.9607843,1
}
Item
{
Name = Highlands
Color = 0.145098,0.9960784,0.003921569,1
}
Item
{
Name = Lowlands
Color = 0.9960784,0.003921569,0.003921569,1
}
Item
{
Name = Mara
Color = 0,0.9921569,0.9098039,1
}
Item
{
Name = Minor Craters
Color = 0.03529412,0.7254902,0.1490196,1
}
Item
{
Name = Major Crater
Color = 0.9960784,0.9607843,0.003921569,1
}
}
}
Item
{
Name = Gilly
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Midlands
Color = 0.8901961,0,0.9960784,1
}
Item
{
Name = Lowlands
Color = 0.9176471,0.007843138,0.3843137,1
}
Item
{
Name = Highlands
Color = 0.02352941,0,0.9960784,1
}
}
}
Item
{
Name = Pol
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Poles
Color = 0.09411765,1,0,1
}
Item
{
Name = Lowlands
Color = 1,0.6352941,0,1
}
Item
{
Name = Highlands
Color = 1,0,0,1
}
Item
{
Name = Midlands
Color = 0,0.1882353,1,1
}
}
}
Item
{
Name = Dres
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Poles
Color = 1,0.9647059,0,1
}
Item
{
Name = Midlands
Color = 0,1,0.9176471,1
}
Item
{
Name = Lowlands
Color = 1,0,0.8,1
}
Item
{
Name = Ridges
Color = 0.1058824,0.3568628,0.172549,1
}
Item
{
Name = Highlands
Color = 0.9960784,0.5372549,0,1
}
Item
{
Name = Impact Craters
Color = 0.09411765,0,1,1
}
Item
{
Name = Impact Ejecta
Color = 1,0.682353,0,1
}
Item
{
Name = Canyons
Color = 1,0,0,1
}
}
}
Item
{
Name = Eeloo
DefaultColor = 0,0,0,0
BiomeColors
{
Item
{
Name = Poles
Color = 1,0,0,1
}
Item
{
Name = Glaciers
Color = 0.6862745,0.3019608,0.8784314,1
}
Item
{
Name = Lowlands
Color = 1,0,0.8235294,1
}
Item
{
Name = Highlands
Color = 1,0.7294118,0,1
}
Item
{
Name = Ice Canyons
Color = 0,1,0.09411765,1
}
Item
{
Name = Craters
Color = 0.03529412,0.05098039,0.7254902,1
}
Item
{
Name = Midlands
Color = 0.2666667,0.7058824,0.9529412,1
}
}
}
}
}
DustColorDefinitions

As a little bonus, by looking at vessel.landedAt as well as biome, you could add entries in here for specific collidable objects -- "LaunchPad" etc

Link to comment
Share on other sites

Well, grind me up and feed me to the space monkeys... That's awesome. I just woke up and I'm so not ready to process that, but it looks like a cure from where I'm sitting. Thanks a bunch.

UPDATE: alright, I'm a bit fresher now and hopping to it. I hope you don't mind, but I'm going to take the easy way out at the first and pretty much copy what you posted word for word and see where it takes me. This is what always messed me up in classes: they try to teach you by showing you how it starts and then giving you a problem that cannot be solved by what you have and expect you to figure it out. I learn better by taking apart a complete example of exactly what I need and morphing it into my own. That's why I normally will go to the end of my math book and start tearing apart the final questions of the entire class of thought and trying to make them function for me. It really bugs my teachers though, which could be absolutely hilarious and quite entertaining if is wasn't for the fact that they are deciding my future by grading my work.

In this context, I had completed (or functional at least) mods to look at, some of which I didn't have the source for and had to cheat by using ILSpy (I'm so sneaky) but none of them really did what I was trying to do in a way that would make sense because they weren't handling the data I needed handled, and almost all of them were not just loading but also saving way too much information for my needs.

Anyway, I think I'm going to get there now.

EDIT2: Okay, so it's not liking something in there:


[COLOR=#0000ff][B] public[/B][/COLOR] [COLOR=#ff0000]class[/COLOR] [COLOR=#004085]DustColorDefinitions[/COLOR] : [COLOR=#004085]IPersistenceLoad[/COLOR], [COLOR=#004085]IPersistenceSave[/COLOR]
{
[Persistent] [COLOR=#0000ff][B]private[/B][/COLOR] [COLOR=#004085]List[/COLOR]<[COLOR=#8b0000]BodyDustColorInfo[/COLOR]> [I]BodyDustColors[/I] = [U][COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085]List[/COLOR]<[COLOR=#8b0000]BodyDustColorInfo[/COLOR]>();[/U]
[COLOR=#006400]//[COLOR=#006400](underlined above) C[/COLOR]annot implicitly convert type List<?> to List<BodyDustColorInfo>[/COLOR]
[Persistent] [COLOR=#0000ff][B]private[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]DefaultColor[/I] = [COLOR=#004085][B]Color[/B][/COLOR].clear;

[COLOR=#0000ff][B]private[/B][/COLOR] [COLOR=#004085]Dictionary[/COLOR]<[COLOR=#004085]CelestialBody[/COLOR],
[COLOR=#8b0000]BodyDustColorInfo[/COLOR]>
[I]_dustColors[/I] = [U][COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085]Dictionary[/COLOR]<[COLOR=#004085]CelestialBody[/COLOR], [COLOR=#8b0000]BodyDustColorInfo[/COLOR]>();[/U]
[COLOR=#006400]//[COLOR=#006400](underlined above) C[/COLOR]annot implicitly convert type Dictionary<CelestialBody> to Dictionary<CelestialBody, BodyDustColorInfo>[/COLOR]

[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [COLOR=#191970][B]GetDustColor[/B][/COLOR]([COLOR=#004085]CelestialBody[/COLOR] body, [COLOR=#ff0000][B]double[/B][/COLOR] lat, [COLOR=#ff0000][B]double[/B][/COLOR] lon)
{
[COLOR=#8b0000]BodyDustColorInfo[/COLOR] biomeColors;
[COLOR=#004085]BiomeDustColorInfo[/COLOR] dustColor;

[COLOR=#0000ff][B]if[/B][/COLOR] (![I]_dustColors[/I].[COLOR=#191970][B]TryGetValue[/B][/COLOR](body, [U][COLOR=#ff1493][B]out[/B][/COLOR] biomeColors[/U]))
[COLOR=#006400]//(underlined above) Cannot implicitly convert type ? to BodyDustColorInfo[/COLOR]
[COLOR=#000080]return[/COLOR] [I]DefaultColor[/I];

var biome = [COLOR=#004085]FlightGlobals[/COLOR].ActiveVessel == [B]null[/B]
? [COLOR=#ff0000]string[/COLOR].[I]Empty[/I]
: ([COLOR=#ff0000]string[/COLOR].[COLOR=#191970][B]IsNullOrEmpty[/B][/COLOR]([COLOR=#004085]FlightGlobals[/COLOR].ActiveVessel.[I]landedAt[/I])
? [COLOR=#004085]ScienceUtil[/COLOR].[COLOR=#191970][B]GetExperimentBiome[/B][/COLOR](body, lat, lon)
: [COLOR=#004085]Vessel[/COLOR].[COLOR=#191970][B]GetLandedAtString[/B][/COLOR]([COLOR=#004085]FlightGlobals[/COLOR].ActiveVessel.[I]landedAt[/I]));

[COLOR=#000080]return[/COLOR] biomeColors.[COLOR=#8b0000]GetDustColor[/COLOR](biome);
}


[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#ff0000]void[/COLOR] [COLOR=#191970][B]PersistenceLoad[/B][/COLOR]()
{
[I]_dustColors[/I] = [I]BodyDustColors[/I]
.[COLOR=#191970][B]Where[/B][/COLOR](info => [COLOR=#004085]FlightGlobals[/COLOR].Bodies.[COLOR=#191970][B]Any[/B][/COLOR](b => b.[I]bodyName[/I] == info.[COLOR=#8b0000]Name[/COLOR]))
.[COLOR=#191970][B]ToDictionary[/B][/COLOR](
info => [COLOR=#004085]FlightGlobals[/COLOR].Bodies.[COLOR=#191970][B]Single[/B][/COLOR](b => b.[I]bodyName[/I] == info.[COLOR=#8b0000]Name[/COLOR]), c => c);
}


[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#ff0000]void[/COLOR] [COLOR=#191970][B]PersistenceSave[/B][/COLOR]()
{
[COLOR=#0000ff][B]if[/B][/COLOR] (![I]BodyDustColors[/I].[COLOR=#191970][B]Any[/B][/COLOR]())
{
[COLOR=#008000]// generate default config[/COLOR]
[I]BodyDustColors[/I] = [U][COLOR=#004085]FlightGlobals[/COLOR].Bodies.[COLOR=#191970][B]Where[/B][/COLOR](cb => cb.[I]BiomeMap[/I] != [B]null[/B]).[COLOR=#191970][B]Select[/B][/COLOR](b => [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#8b0000]BodyDustColorInfo[/COLOR]
{
[COLOR=#8b0000]DefaultColor[/COLOR] = [I]DefaultColor[/I],
[COLOR=#8b0000]Name[/COLOR] = b.[I]bodyName[/I],
[COLOR=#8b0000]BiomeColors[/COLOR] = b.[I]BiomeMap[/I].[I]Attributes[/I]
.[COLOR=#191970][B]GroupBy[/B][/COLOR](attr => attr.[I]name[/I])
.[COLOR=#191970][B]Select[/B][/COLOR]([COLOR=#000080]group[/COLOR] => [COLOR=#000080]group[/COLOR].[COLOR=#191970][B]First[/B][/COLOR]())
.[COLOR=#191970][B]Select[/B][/COLOR](attr => [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085]BiomeDustColorInfo[/COLOR] {Color = attr.[I]mapColor[/I], Name = attr.[I]name[/I]}).[COLOR=#191970][B]ToList[/B][/COLOR]()
}).[COLOR=#191970][B]ToList[/B][/COLOR]();[/U]
[COLOR=#006400]//(the entire underlined segment above) Cannot implicitly convert type[/COLOR] [COLOR=#006400]List<?> to List<BodyDustColorInfo>[/COLOR]
}
}
}

So yeah, something not quite right in there. My guess is I need to be "using" something more than the standard set, or that there's an extra reference I need.

EDIT3: I got it! Wow, that was a crazy one. So, it seems you named the first class "BiomeDustColorInfo" but proceeded to use "BodyDustColorInfo" in most of the second class. Switching out the name fixed every error I was getting.

EDIT4: Okay, so let me speak directly from my brain here and ask a few questions...

So, what it looks like is that this code will generate (if not already found) all of those locations/biomes in the file of choice upon initializing the plugin, but if the file exists will simply use what it is given. What happens if it finds incomplete data? Will it fill in the incomplete data, or will it simply use what it has and get grumpy when we ask for more?

Also, in your example config file, were those color defaults selected by you, or did the code automatically generate an appropriate color for that biome?

Finally, the big question: I need to grab the color information and plug that into the original code for the dust particle creator. Is the current format of the color data going to be compatible, or will I need to convert it into some other format? Here's a new sample of what I have at this time for using the color data to generate the dust plumes:


[COLOR=#ff0000]void[/COLOR] [COLOR=#191970][B]DustParticles[/B][/COLOR] ( [COLOR=#ff0000][B]float[/B][/COLOR] speed, [COLOR=#004085][B]Vector3[/B][/COLOR] contactPoint, [COLOR=#004085]Collider[/COLOR] col )
{
[COLOR=#0000ff][B]if[/B][/COLOR] (![I]dustEffects[/I])
[COLOR=#000080]return[/COLOR];
[COLOR=#0000ff][B]if[/B][/COLOR] (speed > [I]minScrapeSpeed[/I])
{
[COLOR=#008000]// Set dust biome colour.[/COLOR]
[COLOR=#0000ff][B]if[/B][/COLOR] (![COLOR=#191970][B]Equals[/B][/COLOR]([I]dustAnimator[/I], [B]null[/B]))
{
[COLOR=#004085][B]Color[/B][/COLOR] BiomeColor = [COLOR=#191970][B]GetBiomeColour[/B][/COLOR](col);
[COLOR=#0000ff][B]if[/B][/COLOR] (![COLOR=#191970][B]Equals[/B][/COLOR](BiomeColor, [I]dustColor[/I]))
{
[COLOR=#004085][B]Color[/B][/COLOR] [] colors = [I]dustAnimator[/I].colorAnimation;
colors[[COLOR=#00008b]0[/COLOR]] = BiomeColor;
colors[[COLOR=#00008b]1[/COLOR]] = BiomeColor;
colors[[COLOR=#00008b]2[/COLOR]] = BiomeColor;
colors[[COLOR=#00008b]3[/COLOR]] = BiomeColor;
colors[[COLOR=#00008b]4[/COLOR]] = BiomeColor;
[I]dustAnimator[/I].colorAnimation = colors;
[I]dustColor[/I] = BiomeColor;
}
}
[COLOR=#0000ff][B]else[/B][/COLOR]
[COLOR=#000080]return[/COLOR];

[I]dustFx[/I].transform.position = contactPoint;
[I]dustFx[/I].particleEmitter.maxEnergy = speed / [I]maxDustEnergyDiv[/I];
[I]dustFx[/I].particleEmitter.maxEmission = [COLOR=#004085][B]Mathf[/B][/COLOR].[COLOR=#191970][B]Clamp[/B][/COLOR]((speed * [I]maxDustEmissionMult[/I]), [I]minDustEmission[/I], [I]maxDustEmission[/I]);
[I]dustFx[/I].particleEmitter.[COLOR=#191970][B]Emit[/B][/COLOR]();
}
}

[COLOR=#008000] // Color format: RGBA (0-1, decimal percentage)[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]genericDustColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.75[/COLOR]f, [COLOR=#00008b]0.75[/COLOR]f, [COLOR=#00008b]0.75[/COLOR]f, [COLOR=#00008b]0.007[/COLOR]f);
[COLOR=#008000]// Grey 210 210 210[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]dirtColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.65[/COLOR]f, [COLOR=#00008b]0.48[/COLOR]f, [COLOR=#00008b]0.34[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Brown 165, 122, 88[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]lightDirtColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.65[/COLOR]f, [COLOR=#00008b]0.52[/COLOR]f, [COLOR=#00008b]0.34[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Brown 165, 132, 88[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]sandColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.80[/COLOR]f, [COLOR=#00008b]0.68[/COLOR]f, [COLOR=#00008b]0.47[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Light brown 203, 173, 119[/COLOR]
[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [I]snowColour[/I] = [COLOR=#008b8b][B]new[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] ([COLOR=#00008b]0.90[/COLOR]f, [COLOR=#00008b]0.94[/COLOR]f, [COLOR=#00008b]1[/COLOR]f, [COLOR=#00008b]0.0125[/COLOR]f);
[COLOR=#008000]// Blue-white 230, 250, 255[/COLOR]

[COLOR=#0000ff][B]public[/B][/COLOR] [COLOR=#004085][B]Color[/B][/COLOR] [COLOR=#191970][B]GetBiomeColour[/B][/COLOR] ( [COLOR=#004085]Collider[/COLOR] c )
{
[COLOR=#0000ff][B]switch[/B][/COLOR] ([COLOR=#004085]FlightGlobals[/COLOR].ActiveVessel.mainBody.name)
{
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Kerbin"[/COLOR]:
[COLOR=#0000ff][B]if[/B][/COLOR] ([COLOR=#191970][B]IsPQS[/B][/COLOR](c))
{
[COLOR=#ff0000]string[/COLOR] biome = [COLOR=#191970][B]GetCurrentBiomeName[/B][/COLOR]();
[COLOR=#0000ff][B]switch[/B][/COLOR] (biome)
{
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Water"[/COLOR]: [COLOR=#008000]//Anything here would be the sea-bottom.[/COLOR]
[COLOR=#000080]return[/COLOR] [I]lightDirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Grasslands"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Highlands"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Shores"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]lightDirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Mountains"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Deserts"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]sandColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Badlands"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Tundra"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Ice Caps"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]snowColour[/I];
[COLOR=#0000ff][B]default[/B][/COLOR]:
[COLOR=#000080]return[/COLOR] [I]dirtColour[/I];
}
}
[COLOR=#000080]return[/COLOR] [I]genericDustColour[/I];
[COLOR=#0000ff][B]case[/B][/COLOR] [COLOR=#0000ff]"Duna"[/COLOR]:
[COLOR=#000080]return[/COLOR] [I]sandColour[/I];
[COLOR=#0000ff][B]default[/B][/COLOR]:
[COLOR=#000080]return[/COLOR] [I]genericDustColour[/I];
}
}

I assume that I could now likely get rid of the specifically handled body names and instead simply grab the vessel's current body/biome and query a method in the other file (I stuck all the other stuff in a file I uniquely, as if, named "Config.cs"... ingenious naming converntion I have there, aint it?) for the matching configuration.

I also would need to make sure it's going to return to the default color for each body (which is going to probably just be a generic matching color to the body's apparent color from orbit) when no biome match can be found, in those rare cases where the body doesn't have them set up, or in the case of a mod-added celestial body.

This is exciting... You have no idea how long I've been trying to figure out how this is done (at least three weeks between school, school, and more of... you guessed it... school).

EDIT... whatever number we're on:

Okay, so I tried to run it really fast to see what would happen and it wasn't a complete success. It seems that it can't even load these new classes right off the bat. Here's what it put in the log before KSP crashed:

[ERR 13:08:17.263] AssemblyLoader: Exception loading 'DustFX': 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

Additional information about this exception:

System.TypeLoadException: Could not load type 'DustFX.Configs.BiomeDustColorInfo' from assembly 'DustFX, Version=1.0.5547.21743, Culture=neutral, PublicKeyToken=null'.

System.TypeLoadException: Could not load type 'DustFX.Configs.DustColorDefinitions' from assembly 'DustFX, Version=1.0.5547.21743, Culture=neutral, PublicKeyToken=null'.

System.TypeLoadException: Could not load type 'DustFX.Configs.DustColorFileWriter' from assembly 'DustFX, Version=1.0.5547.21743, Culture=neutral, PublicKeyToken=null'.

System.TypeLoadException: Could not load type '<>c__DisplayClass8' from assembly 'DustFX, Version=1.0.5547.21743, Culture=neutral, PublicKeyToken=null'.

System.TypeLoadException: Could not load type '<>c__DisplayClassa' from assembly 'DustFX, Version=1.0.5547.21743, Culture=neutral, PublicKeyToken=null'.

I renamed that really long vague class/function/whatever-you-call-it to DustColorFileWriter for lack of anything better to call it. Anyway, to make sure it wasn't just a random KSP loader bug, I relaunched and, while successfully laoding up assets now, it still put the above bit into the log. So, I've got some issues in there somewhere.

Edited by Gaalidas
Link to comment
Share on other sites

So, what it looks like is that this code will generate (if not already found) all of those locations/biomes in the file of choice upon initializing the plugin, but if the file exists will simply use what it is given. What happens if it finds incomplete data?

It depends on where its attempt to find the color fails. If you ask it for a CelestialBody and there aren't any entries for that body, you get the default overall color (DustColorDefinitions.DefaultColor). If instead it's a valid body but there's no entry for the current biome or LandedAt string, you get the default color for that planet (BodyDustColorInfo.DefaultColor). You could make a small edit to make sure all the planets are accounted for but it might lead to strange results. For instance, if the user has installed a planet pack of some kind that renames all the planets, the current "generate default" is going to result in some odd colored dust/sparks.

Also, in your example config file, were those color defaults selected by you, or did the code automatically generate an appropriate color for that biome?

Merely used the internal map color to give it a non-transparent initial value. Querying the actual diffuse map would be a great idea though.

Finally, the big question: I need to grab the color information and plug that into the original code for the dust particle creator. Is the current format of the color data going to be compatible, or will I need to convert it into some other format? Here's a new sample of what I have at this time for using the color data to generate the dust plumes:

Yes, you should be able to outright replace your entire GetBiomeColour method with GetDustColor. The only real difference is that I removed the collider inspection you do in yours and use the vessel landedAt string instead. I was thinking that you might want to customize dust based on the exact object the vessel is traveling on but that part is untested for anything but a stationary vessel so might need tweaking

As for the loading error: are you targeting .Net 3.5? Is your source posted anywhere?

Link to comment
Share on other sites

Ah, so it's specific to 3.5? There are only a few recompiles of other mods that reacted badly to switching to 4.0. The reason is that when I load a project that uses 3.5, it tells me something is missing that it needs. By experimentation, I found that 4.0 got rid of that problem. I am unsure why it matters in these few cases, but in most other does not. I am unsure how I could rectify the situation of having to reference version 3.5.

I actually haven't posted my source anywhere at this time. It doesn't even work fully yet, and it's very specifically aimed at the parts found in the Kerbal Foundries mod, so it's really not too useful outside of that context.

Edited by Gaalidas
Link to comment
Share on other sites

KSP is compiled against .NET 3.5 (effectively), so you need to do the same to make sure everything works.

Switching from 4.5 to 3.5 on a new project gives me an error about the Microsoft.CSharp (IIRC) reference being lost. Just delete the reference if that's the thing that's failing, you don't need it.

Link to comment
Share on other sites

that is not what's really happening here. When I open a project that previously referenced framework 3.5, I see this:

The reference assemblies for framework ".NETFramework,Version=v3.5" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend.

However, upon trying to find the required SDK, I'm being told that installing this older SDK package is not recommended and I worry about it causing problems with other projects that use a different framework version. Besides, actually finding a proper download for these things is near impossible. Microsoft's own site says that a different package is recommended, but it doesn't link me to that package that it suggests, so I can't actually find it.

I just don't undrstand why it's a problem here due to the fact that 90% of the other mods, all quite complicated pieces of work, in which I convert to framework 4.0, function perfectly, and yet this one will not even load properly with rather vague errors that do not exist when compiling or writing the code itself. The only thing that changes, that I can see, when changing the targeted framework version, is that a new reference gets added (Microsoft.CSharp) and the error about a missing reference SDK is removed.

- - - Updated - - -

Yes, you should be able to outright replace your entire GetBiomeColour method with GetDustColor. The only real difference is that I removed the collider inspection you do in yours and use the vessel landedAt string instead. I was thinking that you might want to customize dust based on the exact object the vessel is traveling on but that part is untested for anything but a stationary vessel so might need tweaking.

That's interesting... but I think it might be a little beyond my scope for the time being. It would only really come into usefulness if the surface of a body was covered in custom landscape using models that are separate from the body surface in which I could match the dust color based on their apparent material type. At the KSC, however, I think the pavement and the grass is all part of the same false-landscape object, so I wouldn't necessarily be able to map only a slight barely-visible trail to the paved areas and a grassy/dirty trail to the grass areas. As it is, I'm just going to further tone down the default dust effect and let that take over when the collision with the actual planetary surface is lost. I may even, in the far future, re-implement the effects from CollisionFX (if I can get in touch with the original author for some cooperation) so that the tracks, for instance, can create some very subdued sparking when scraping against the pavement during tight turns.

Good to have that option available, though. Right now, my best idea for how to make it all work, was simply to replace the switch I have currently with a call to the GetDustColor method which, I believe, takes a name for the body you're checking for the settings of, and pass the name of the body/biome that is found in the method that I currently have for figuring out what the vessel is colliding with. I'm really not knowledgeable enough with these things to rewrite the method for using a different detection method than what is used now. See, this isn't a completely original piece of work, but rather a re-purposing of CollisionFX, which was not authored by me.

Link to comment
Share on other sites

I just don't undrstand why it's a problem here due to the fact that 90% of the other mods, all quite complicated pieces of work, in which I convert to framework 4.0, function perfectly, and yet this one will not even load properly with rather vague errors that do not exist when compiling or writing the code itself.

All it would take is a single bit to change between the 3.5 implementation and the 4.0 implementation and things won't behave. This is why 4+ falls over without any ryhme or reason.

Assuming you're on Win8(.1) since you don't have 3.5 (scroll down to the bit about enabling in the control panel): https://msdn.microsoft.com/en-us/library/hh506443%28v=vs.110%29.aspx

Link to comment
Share on other sites

Your assumption is false, I wouldn't be using windows 8 if you paid me. It's too weird. I'm running Windows 7 ultimate.

I also just attempted to install the SDK for 3.5 and it made absolutely no difference when trying to change the project into a 3.5 framework project.

EDIT: I have tried everything I can think of from installing .net framework 3.5, 4.5, 4.0, etc and I am still being told that the SDK or Targeting Pack for .net 3.5 is required. I am told online that you cannot install it on Windows 7 because it's included, but it apparently is NOT included because I can't reference it or compile with it. When I search explicitly for ".net framework 3.5 SDK" on the microsoft download site, I am presented with several pages of search results containing everything except the freaking SDK for 3.5. I get 2.0, 4.0, 4.5, but NOT 3.5 even though I specifically entered "3.5" into the search area. No matter what, the only .net framework version that I can successfully use is 4.0, and only 4.0. Anything else and it fails to even build the project. This is going to drive me absolutely insane.

Edited by Gaalidas
Link to comment
Share on other sites

It's a grand mystery, indeed. I attempted to compile it without the proper stuff, letting it use whatever it could find that would work, and... oddly enough, no more errors on loading up KSP. We'll see if it actually does anything though.

- - - Updated - - -

The thing about that download is that the file won't even run. Even after I extract it manually and try to run the setup file, it works for half a second and then quits with no message or anything. My guess is that it will only function if it doesn't detect an even or higher version already installed. That means, if I can compile under .net 4.0, I will never be able to compile under anything lower than that because it can't be installed at the same time. Searches on the subject seem to confirm that, but at the same time those same results say that having a higher version of the framework installed also allows you to make use of any previous versions, which I am discovering is not the case. At this time I'm calling it an issue with SharpDevelop (the software I use to develop this stuff) and it's probably not an error at all, but simply a warning that I might not be able to effectively prepare my project for that specific platform without the full SDK for that version installed. Considering KSP uses a framework that is a bit behind the times, compiling for that specific platform with the idea that the intended audience will need to upgrade to that version is unlikely to be the case since we will all likely have a version much higher than the requested version installed. It still remains a mystery as to why I can run some plugins in KSP with 4.0, and others on the boards have reported no issue with using 4.5 even, but this specific stuff will only function under 3.5. It's a very confusing mystery.

Link to comment
Share on other sites

A plugin compiled for 4 or 4.5 runs fine until mono find a CIL instruction not part of the 3.5 specs. At that point you get a runtime exception. So it is a really bad idea since you can't be sure all your code will work.

Link to comment
Share on other sites

I'm probably asking for trouble by not using VS at all.

- - - Updated - - -

A plugin compiled for 4 or 4.5 runs fine until mono find a CIL instruction not part of the 3.5 specs. At that point you get a runtime exception. So it is a really bad idea since you can't be sure all your code will work.

I'm all out of options though, so if it's working now I'm going to run with it.

Link to comment
Share on other sites

I'm probably asking for trouble by not using VS at all.

What do you mean by that ?

If you don't want VS and want command line compiling then install mono and/or Monodevelop then, you won't need the 3.5 .NET SDK that way.

And you can have all the .NET SDK installed in parrallel. I don't know what is going on with your installs or what you are doing but I guess you are doing something wrong.

Releasing a mod targeting 4.5 is asking for trouble. Explain what you are doing instead of making post saying it does not work.

Link to comment
Share on other sites

What do you mean by that ?

If you don't want VS and want command line compiling then install mono and/or Monodevelop then, you won't need the 3.5 .NET SDK that way.

And you can have all the .NET SDK installed in parrallel. I don't know what is going on with your installs or what you are doing but I guess you are doing something wrong.

Releasing a mod targeting 4.5 is asking for trouble. Explain what you are doing instead of making post saying it does not work.

First, I mean that I do not use Visual Studio, and there's more out there available than Mono to fill in the gaps. Command-line would actually make things very difficult for me. Do a little more research and you'll find that there's more to this world than VS and Mono. You'll be amazed, I assure you.

Second, I cannot have them all installed in tandem, as they won't install together. Declaring that what I am saying is false without providing a solution to the problem is just being argumentative. I'm sitting right here, double clicking on a setup file that refuses to run. I haven't been messing with PCs since i was 3 years old on a PC Junior (no hard drive, two literally floppy disks just to boot it up) to miss some obvious user error that would lead you to point out that you believe I can have something installed that, as i will assure you right now, refuses to even try to install. In fact, I've been told that if I have the 4.5 edition, I also have all the others, yet my compiler refuses to use anything but version 4 in the correct manner. However, it seems that compiling under 3.5 even when it cannot find the correct assembles has worked, because KSP has stopped returning load errors.

And third, I have not simply posted a message saying "in does not work." I have, instead, been having a long conversation across several messages. I am not going to restate the entire conversation in each message in an attempt to explain myself fully when one person decides that I'm taking bovine excrement when i claim that something isn't workiing as expected. So, if you take time to read the posts you have missed you'll find out that I have explained it. If you are unable to understand that still, then I'm afraid I cannot help you because I lack the professional degrees to properly diagnose the malfunction happening there. I'm sorry for that, but I'm sure you'll find help eventually and I don't think it will be life threatening.

Edited by Gaalidas
Link to comment
Share on other sites

Yes you are doing nothing more than posting "it does not work". You don't explain the tool you use, how you are trying to compile or how you install. That makes it quite hard to help you.

And I'll be happy to know what other compiler there is for c# beside MS .NET and Mono (And I mean compiler, not GUI). Please do enlighten me.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

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...