Jump to content

.20 And mods


DYJ

Recommended Posts

Just a heads up: In 0.19.1, I was able to use

ConfigNode.Load("myfile.cfg")

and

ConfigNode.Save("myfile.cfg")

and the files were put in my plug-in directory.

That does not work anymore in 0.20. Save was putting the file in the root KSP directory. And Load was never able to find the file, either in the plug-in directory or in the root KSP directory.

I found that I can get it to work by doing this instead:

string filename = IOUtils.GetFilePathFor(this.GetType(), "myfile.cfg");
ConfigNode.Load(filename); // or Save(filename)

Link to comment
Share on other sites

I'm having an odd problem...if I install no legacy addons, everything loads as normal (parts, etc). But if I install legacy addons, although they appear to be loaded during the initial loading screen, the stock parts are not available in-game and only some of the legacy parts are. What am I doing wrong?

Link to comment
Share on other sites

I'm having an odd problem...if I install no legacy addons, everything loads as normal (parts, etc). But if I install legacy addons, although they appear to be loaded during the initial loading screen, the stock parts are not available in-game and only some of the legacy parts are. What am I doing wrong?

Installing a part that isn't 0.20 compatible. As I posted above, for some types of error while loading parts the game will skip the rest of the part loading stage. The output log (KSPData/output_log.txt) or debug console (alt+f2) should show you which part is causing the problem.

Link to comment
Share on other sites

So exactly what should my GameData/Squad folder look like? What folders do I have to create for installing mods?

0.20 Mods can go anywhere within the gamedata folder; you don't need any folder structure, just put them there and it'll be fine.

Link to comment
Share on other sites

So exactly what should my GameData/Squad folder look like? What folders do I have to create for installing mods?

The recommendation is {KSP}/GameData/<modname>/<mod files>

Putting everything for a mod in its own mod folder keeps everything together, and makes it easier to upgrade or uninstall the mod. The mod's files can be organized in any way you want within the folder.

Link to comment
Share on other sites

0.20 Mods can go anywhere within the gamedata folder; you don't need any folder structure, just put them there and it'll be fine.

IF you deviate from the structure made by the mod creator, you can break stuff loading from the game database, if the plugin uses that.

I load sounds from Firespitter/Sounds in the game database. If the sounds had been moved, that would break.

With increasing use of parts fetching resources from other parts' assets, I think this will become even more of a thing to keep in mind.

Link to comment
Share on other sites

That is correct, but in general: if a mod has been packaged in a relatively sane manner, then the top level directory should either be called GameData, or the name of the mod. In the case of the former, copy the contents of GamesData into the KSP GameData folder, and for the latter just copy the unziped mod into GameData.

Link to comment
Share on other sites

Ok so something like this?

KSP/GameData/Squad

KSP/GameData/KW rocketry

KSP/GameData/MechJeb

and so on?

Just want to make sure Im doing this right before I start up the new missions! :D Thanks for the help so far guys!

Just like that

Link to comment
Share on other sites

Jesus what a mess. Still dont understand what the hell I am suppose to do with plugindata. Why cant everything just be in a flaming Mods folder? Why is it all in gamedata? I thought that was just for the devs to use. Why do I still have another parts and plugins folder then - is that for old mods or something? Cant get my head around all this.

Link to comment
Share on other sites

Ok so something like this?

KSP/GameData/Squad

KSP/GameData/KW rocketry

KSP/GameData/MechJeb

and so on?

Just want to make sure Im doing this right before I start up the new missions! :D Thanks for the help so far guys!

I did this with Mechjeb 2.0 and did not work.

Link to comment
Share on other sites

Mechjeb should go in the KSP folder with those first folders with ships and plugins. Youll have to create the PluginData folder possibly in there with those too :)

I think I got this figured out a little better. Sometimes parts wont appear in-game but I can fix it sometimes :P

I love KSP :)

Link to comment
Share on other sites

I noticed a problem with the change. If you have a ship built with parts from mods and the mod author updates to the new structure you cannot load your ship anymore. the really bad thing here is that immediately after you get the error message the game immediately saves your game. This results in losing the whole savegame because the flights are removed.

I didn't took a look into the craft files but i think the used parts are listed with absolute paths like KSP_OS\Parts\foo\bar\ so if you move your files to the new system the path changes too KSP_OS\GameData\foo\Parts\foo\bar\.

Suggestion: Just rename GameData to Mods and place all of your stock files into KSP_OS instead of Mods (just like before). This way we can very easily restore factory default by just renaming the directory Mods to something else. The loading preference (if there are parts with the same name) should be the Mods directory - otherwise it would be kinda useless ;)

Do i need a config file for Ships (stored in KSP_WIN\GameData\MyMod\Ships\...) because here are only stock ships loaded. If i place the files in KSP_WIN\Ships\ or KSP_WIN\Saves\...\ i can use them.

Thanks :)

Link to comment
Share on other sites

I have everything stored in GameData even if the Addon was not made for the new structure but everything works fine! Mechjeb is loaded and all the other Addons i normally use. I just can't load any ship stored in the GameData directory but only if they're stored in either Ships directory or below Saves.

To be honest there is still a big problem with the new system. You have a savegame with some flights active. One of the ships uses a part contained in a mod. The mod gets updated and moves its files from KSP_OS\Parts to GameData. Now the internal USL to the parts is different. If you load your savegame you get an error that a ship could not get loaded because of missing parts. your flights are cancelled and the game automatically saves your game. You sucessfully destroyed your whole savegame! If you now put the missing parts back into the KSP_OS\Parts directory and try to load that savegame again: fail. the game already overwrote it just as the error message appeared the first time.

I really don't know why we have to invent the wheel again. Back at Quake 1 times such a system already existed. stock files are stored in these pak files (ordinary zip files) and all custom (modded) files are stored in the same directory but with subdirectories, etc. That system didn't had the problem with different internal urls ...

Link to comment
Share on other sites

One of the ships uses a part contained in a mod. The mod gets updated and moves its files from KSP_OS\Parts to GameData. Now the internal USL to the parts is different. If you load your savegame you get an error that a ship could not get loaded because of missing parts.

Given the stock parts have also moved that may not be the problem. And even if it is, the game is in development and this sort of thing should be expected. The developers shouldn't spend time on backwards compatibility at this point.

Link to comment
Share on other sites

  • 2 years later...
I'm making my own engine sound handler that loads sounds from the game database and plays it according to thrust.

For the very simple sound loading code/test, check this thread, otherwise full code:

plugin


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

public class FSengineSounds : PartModule
{
[KSPField]
public string engage;
[KSPField]
public string running;
[KSPField]
public string power;
[KSPField]
public string disengage;
[KSPField]
public string flameout;
[KSPField]
public string warning;
[KSPField]
public float powerFadeInSpeed = 0.02f;
[KSPField]
public float powerFadeInDelay = 0.0f;
[KSPField]
public float powerVolume = 1.0f;
[KSPField]
public float engageVolume = 1.0f;

[KSPField]
public float powerPitchBase = 0.8f;
[KSPField]
public float thrustAddedToPowerPitch = 0.3f;

[KSPField]
public bool useDebug = false;
[KSPField]
public bool showVolumeDebug = false;

private ModuleEngines engine;
private bool oldIgnitionState;
private bool oldFlameOutState;
private float currentPowerFadeIn;
private float currentPowerDelay;

private string doesExist = "...";

public FXGroup engageGroup;
public bool engageAssigned;
public FXGroup runningGroup;
public bool runningAssigned;
public FXGroup powerGroup;
public bool powerAssigned;
public FXGroup disengageGroup;
public bool disengageAssigned;
public FXGroup flameoutGroup;
public bool flameoutAssigned;
public FXGroup warningGroup;
public bool warningAssigned;

/// <summary>
/// Fills an FXGroup with sound values
/// </summary>
/// <param name="group">The group that will receive a new sound</param>
/// <param name="name">The name of the sound in the game database. No file extensions. e.g. Firespitter\Sounds\sound_fspropidle</param>
/// <param name="loop">Does the sound loop by default?</param>
/// <returns></returns>
public bool createGroup(FXGroup group, string name, bool loop)
{
if (name != string.Empty)
{
if (!GameDatabase.Instance.ExistsAudioClip(name))
return false;
group.audio = gameObject.AddComponent<AudioSource>();
group.audio.volume = GameSettings.SHIP_VOLUME;
group.audio.rolloffMode = AudioRolloffMode.Logarithmic;
group.audio.dopplerLevel = 0f;
group.audio.panLevel = 1f;
group.audio.clip = GameDatabase.Instance.GetAudioClip(name);
group.audio.loop = loop;
group.audio.playOnAwake = false;
return true;
}
return false;
}

private void OnDestroy()
{
GameEvents.onGamePause.Remove(new EventVoid.OnEvent(this.FSOnPause));
GameEvents.onGameUnpause.Remove(new EventVoid.OnEvent(this.FSOnUnPause));
}

private void FSOnPause()
{
powerGroup.audio.volume = 0f;
}

private void FSOnUnPause()
{
powerGroup.audio.volume = GameSettings.SHIP_VOLUME;
}

public override void OnStart(PartModule.StartState state)
{
base.OnStart(state);

engageAssigned = createGroup(engageGroup, engage, false);
runningAssigned = createGroup(runningGroup, running, true);
powerAssigned = createGroup(powerGroup, power, true);
disengageAssigned = createGroup(disengageGroup, disengage, true);
flameoutAssigned = createGroup(flameoutGroup, flameout, false);
warningAssigned = createGroup(warningGroup, warning, false);

engine = part.GetComponent<ModuleEngines>();

GameEvents.onGamePause.Add(new EventVoid.OnEvent(this.FSOnPause));
GameEvents.onGameUnpause.Add(new EventVoid.OnEvent(this.FSOnUnPause));

/*public string engage;
public string running;
public string power;
public string disengage;
public string flameout;
public string warning;*/

/* powerGroup.audio = gameObject.AddComponent<AudioSource>();
powerGroup.audio.volume = 1;
powerGroup.audio.Stop();*/
}

public override void OnFixedUpdate()
{
base.OnFixedUpdate();
if (engine != null)
{
if (TimeWarp.WarpMode == TimeWarp.Modes.HIGH && TimeWarp.CurrentRate > 1.1f)
{
if (powerAssigned)
powerGroup.audio.volume = 0f;
}
else
{
// power/running sound
if (engine.getIgnitionState && !engine.getFlameoutState)
{
if (currentPowerDelay > 0f)
currentPowerDelay -= Time.deltaTime;

float adjustedThrustPitch = ((engine.finalThrust / engine.maxThrust) * thrustAddedToPowerPitch) + powerPitchBase;
if (powerAssigned && currentPowerDelay <= 0f)
{
if (currentPowerFadeIn < 1f)
{
currentPowerFadeIn += powerFadeInSpeed;
if (currentPowerFadeIn > 1f)
currentPowerFadeIn = 1f;
}
powerGroup.audio.volume = GameSettings.SHIP_VOLUME * currentPowerFadeIn * powerVolume;
if (!powerGroup.audio.isPlaying)
powerGroup.audio.Play();
powerGroup.audio.pitch = adjustedThrustPitch;
}
}
else
{
if (powerAssigned)
{
if (powerGroup.audio.isPlaying)
powerGroup.audio.Stop();
currentPowerFadeIn = 0f;
currentPowerDelay = powerFadeInDelay;
}
}

// engage sound
if (engageAssigned)
{
if (engine.getIgnitionState && !oldIgnitionState)
{
if (!engine.getFlameoutState)
{
engageGroup.audio.volume = GameSettings.SHIP_VOLUME * engageVolume;
engageGroup.audio.Play();
}
}
oldIgnitionState = engine.getIgnitionState;
}

}

//if (part.temperature > part.maxTemp * warningSound)
//{
// if (timeCounter == 0)
// {
// heatDing.Play();
// }
// timeCounter++;
// if (timeCounter >= 100)
// {
// timeCounter = 0;
// }
//}
//else
//{
// timeCounter = 0;
//}
}
}

public void OnGUI()
{
if (showVolumeDebug)
GUI.Label(new Rect(250f, 300f, 200f, 30f), "engine volume: " + currentPowerFadeIn);
if (useDebug)
{
Rect menuItemRect = new Rect(250f, 200f, 300f, 150f);
Vector2 buttonSize = new Vector2(30f, 30f);
Vector2 menuItemSize = new Vector2(200f, 35f);
if (GUI.Button(new Rect(menuItemRect.x, menuItemRect.y, buttonSize.x, buttonSize.y), "OK"))
{
doesExist = "" + GameDatabase.Instance.ExistsAudioClip(power);
}

if (GUI.Button(new Rect(menuItemRect.x + buttonSize.x + 10f, menuItemRect.y, buttonSize.x, buttonSize.y), "C"))
{
doesExist = "clear";
}

if (GUI.Button(new Rect(menuItemRect.x + ((buttonSize.x + 10f) * 2), menuItemRect.y, buttonSize.x, buttonSize.y), ">"))
{
//powerGroup.audio.clip = GameDatabase.Instance.GetAudioClip(soundName);
//source.PlayOneShot(clip);
powerGroup.audio.Play();
}

GUI.Label(new Rect(menuItemRect.x + ((buttonSize.x + 10f) * 3), menuItemRect.y, menuItemSize.x - buttonSize.x - 10f, buttonSize.y),
"exists: " + doesExist);
menuItemRect.y += 30;
power = GUI.TextField(new Rect(menuItemRect.x + buttonSize.x + 10f, menuItemRect.y, menuItemSize.x - buttonSize.x - 10f, buttonSize.y), power);
}
}
}

part.cfg

PART
{
[...]

// --- general parameters ---
name = FScopterRotorMain
module = Part
author = Snjo

[...]

// --- FX definitions ---

//fx_exhaustLight_yellow = 0.0, -0.1, 0.0, 0.0, 0.0, 1.0, power
//fx_smokeTrail_light = 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, power
fx_exhaustSparks_flameout = 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, flameout

// --- Sound FX definition ---

//sound_fspropstart.wav = engage
//sound_fscoptermain.wav = power
sound_explosion_low = flameout

[...]

MODULE
{
name = FSengineSounds
useDebug = False
showVolumeDebug = True
engage = Firespitter/Sounds/sound_fspropstart
//running =
power = Firespitter/Sounds/sound_fscoptermain
//disengage =
//flameout =
warning = Firespitter/Sounds/sound_fsheatDing
powerPitchBase = 0.8
thrustAddedToPitch = 0.3
powerFadeInSpeed = 0.005
powerFadeInDelay = 1.0
powerVolume = 0.5
engageVolume = 1.5
}

MODULE
{
name = ModuleEngines
[...]
}

}

I'm building this for propeller engines, so I haven't implemented the minimum thrust threshold to stop the sound yet, like you would have with the jet engines.

And not all sounds are playing yet, but you get the idea hopefully.

I realize this is an old post but it's still appropriate to reply here.

After hours of trying to get a simple sound effect to fire in game and getting nothing but Null Reference Exceptions in the log, I found this code and after looking it over managed to incorporate some of what Snjo did (FXgroup) and finally had success. If there's a later reference for how to implement sounds in game, I never found it.

Thanks Snjo!

Link to comment
Share on other sites

A reminder once more: reviving dead threads for a good reason is allowed, but complaining about revived threads is not. It's rude and counterproductive at best – just hit the report button and move on rather than re-reviving the threads.

Although this thread was helpful in this case, it does contain a fair amount of out-of-date information. If the two guides two adding custom sounds in the Mod Development Links Compilation don't cover this aspect, you might start your own thread, linking back here.

Link to comment
Share on other sites

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