Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

As far as I know you can not. The package API is only available in the editor. And some package seems to require some configuration in the game data files. Which package did you want to add?

Link to post
Share on other sites

I'm just updating to 1.8 and hit a snag.  I've got code that's trying to load a button image, but the old Texture2D.LoadImage method is no longer a thing.  (See my example of what used to work in my GetButtonTexture method).

Anybody got a pointer to a different way to load a texture in 1.8?  Thanks.

Derp, got my own answer by RTFM:

 

Edited by NermNermNerm
answered my own question
Link to post
Share on other sites
On 10/22/2019 at 5:33 AM, peteletroll said:

@Lisias, do you plan to file a bug soon? Probably UI_FloatRange, UI_ScaleEdit and UI_FloatEdit have the same root bug. I can file it for you too, maybe someone from @SQUAD can suggest the best way to get this fixed soon.

Hey, I have hard evidences (i.e, proof!!) that I may had misdiagnosed the cause of the problem!

nbbk9N7.png

When the scaling is being called from BDB.dll, it works. When it's called from TweakScale, it does not.

Right now, I'm sniffing into BDB source code to see what it does (or does not) differently from the rest of us.

Edited by Lisias
Kraken count the tyops! (and the grammars!)
Link to post
Share on other sites

I have a new diagnosis, and this one is backed by hard, concrete and reproducible evidences. :) 

The whole story is on TweakScale thread, because one fellow Kerbonaut found one Add'On where the UI_ScaleEdit was working fine!! I tracked down what was working, then I made it broke, then I "fix" one of TweakScale patches - so I have confirmation on both sides of the equation this time.

[KSPField(isPersistant = false, guiActiveEditor = true, guiName = "Scale", guiFormat = "0.000", guiUnits = "m")]
[UI_ScaleEdit(scene = UI_Scene.Editor)]

The thing I think by now can be the problem is the guiUnits (or even the guiFormat?), but it's all wild guesses. All that I know for now is that is on the TweaklScale thread - there's a ScaleType from BDB that works while default ScaleTypes from TweakScale does not. The visible difference is not using the ScaleRtpe data called "suffix" - I will check this properly tomorrow.

See ya later.

Link to post
Share on other sites

Hi all,

I would like to figure out how much science something returns from a certain location if the experiment was recovered or transmitted using these objects: ScienceData data and ScienceExperiment experiment.
I know that data.subjectID gives me a string experimentID@location, and experiment.baseValue and experiment.scienceCap are the base values, but I do not know how to calculate the science at a location with these.

Does someone here know?

(edit: of course I could test all experiments at all locations and hardcode a solution, but I'm looking for a simple algorithm or api call)

edit2: probably solved, just discovered that the ResearchAndDevelopment class has a bunch of science value related methods like ResearchAndDevelopment.GetScienceValue(dataAmount, scienceSubject)

 

edit3: So here's my next question I haven't been able to figure out:

I have a confignode CONTAINED_DATA in which an unknown amount of entries (of the form subjectID:dataAmount) are stored, which looks like this:

CONTAINED_DATA
{
	atmosphereAnalysis@KerbinFlyingLowShores = 200
	atmosphereAnalysis@KerbinSrfLandedLaunchPad = 200
	asdf = 42
}

I have been trying to get my code to add these entries to a dictionary called containedData by looping over the nodes in CONTAINED_DATA:

foreach (ConfigNode dataNodeKey in dataNode.GetNodes())
{
    string key = dataNodeKey.ToString();
    float value = float.Parse(dataNode.GetValue(key));
    containedData.Add(key, value);
    Debug.Log(key + " was added to the dictionary");
}

However, nothing gets added to this dictionary and the log mentions nothing about added keys. I have also tried looping over dataNode.nodes and returning a bunch of objects, which all seem to be empty. Here is the log with comments:

[LOG 22:28:57.178] OnLoad called //the onload method is called in my partmodule
[LOG 22:28:57.178] MODULE //the node is dumped to the log
{
	name = ModuleDataContainer
	isEnabled = True
	stagingEnabled = True
	EVENTS
	{
	}
	ACTIONS
	{
	}
	CONTAINED_DATA //the node (called dataNode in the code) where various entries are stored, which are not known in advance
	{
		atmosphereAnalysis@KerbinFlyingLowShores = 200
		atmosphereAnalysis@KerbinSrfLandedLaunchPad = 200
		asdf = 42
	}
	UPGRADESAPPLIED
	{
	}
}

[LOG 22:28:57.178] GetNodes: ConfigNode[] //dataNode.GetNodes().ToString() returns what seems to be an empty list of confignodes
[LOG 22:28:57.178] nodes.tostring: ConfigNode+ConfigNodeList //dataNode.nodes.ToString() returns something I can't decipher
[LOG 22:28:57.178] Values: System.String[] //dataNode.GetValues().ToString() returns what seems to be an empty list of strings
[LOG 22:28:57.178] This really should work: 200 //directy accessing an entry does work but is not usable when entries are unknown
[LOG 22:28:57.178] containedData is empty //nothing got added to the dictionary
[LOG 22:28:57.178] OnLoad finished

What can I loop over to add the entries to my dictionary and how?

edit4: I created a workaround so that key and value are stored separately (which is a lot less practical), but I still hope there is a solution for key = value entries with unknown keys

Edited by ExtremeTrader
Link to post
Share on other sites
  • 2 months later...

I have a few questions, and I'm going to number them for easier replies. I realize this probably might be a bit vague, but I appreciate any and all responses! 

1. How would I go about intercepting the handover from VAB to Flight mode? I basically need to "catch" the vessel object, that gets handed over from the editor screen to the flight screen and is instantiated, and then stop the flight scene from being loaded. 

2. How do I copy a Unity Scene from code? The current way I'm trying only gives me a reference to the scene I'm trying to copy. I need a full copy that can be loaded from SceneManager. 

3. Can the "environment" (the building and ground model) in the SPH or VAB scene be changed? 

3. Can vessels be "part welded" from code while keeping the individual part's functions? 

4. Can vessels be set to be physics-less (not affected by gravity), and be set as a child object of celestial bodies, eg. like planetary surface structures? 

Link to post
Share on other sites
  • 1 month later...
  • 2 months later...
Posted (edited)

Hello!

Does anyone know how I'd go about getting the world position for a part? 

Vessels have GetWorldPos3D()  but parts seem to have no equivalent.

These two functions:

                    Part.PartToVesselSpacePos;
                    Part.VesselToPartSpacePos;

As well as partTransform()

Combined in some way with the root vessel's world position seem promising, but I am not entirely sure what the best way to approach this is.

 

Thanks :)

 

Edited by nubeees
Another possibly useful function
Link to post
Share on other sites
  • 1 month later...

I'm new to writing plugins in ksp- how do you get the vessel name of the active vessel in flight scene? And also, how would you get current resource consumption/production, and how would you output something to a right click menu in flight.

Edited by Aniruddh
Link to post
Share on other sites

I'll take the easy one.

On 7/21/2020 at 11:47 AM, Aniruddh said:

how do you get the vessel name of the active vessel in flight scene?

FlightGlobals.activeVessel.GetName()

I know resources can be kind of a pain, and I haven't done anything with PAWs… but I think it's as simple as setting an attribute.

Edited by 0111narwhalz
Link to post
Share on other sites
On 7/24/2020 at 8:13 PM, 0111narwhalz said:

I'll take the easy one.

FlightGlobals.activeVessel.GetName()

I know resources can be kind of a pain, and I haven't done anything with PAWs… but I think it's as simple as setting an attribute.

Thanks for the reply! I just found about another method:

this.vessel.name

Does this work, and which one might be better?

EDIT: I got the resource consumption working (to some extant):

using System.Threading
 
int EChash = "ElectricCharge".GetHashCode();
Vessel objVessel = new Vessel();
objVessel.GetConnectedResourceTotals(EChash, out double amount, out double maxAmount, true);
Thread.Sleep(1000);
objVessel.GetConnectedResourceTotals(EChash, out double amount2, out double maxAmount2, true);
double ECperSecond = amount2 - amount;

This tells you EC consumption/usage per second.

Edited by Aniruddh
Found solution (kind of)
Link to post
Share on other sites
On 7/24/2020 at 1:00 PM, Aniruddh said:

this.vessel.name

In this expression, this refers to the VesselModule or PartModule or MonoBehaviour which actually contains it. The problem with this approach is that, firstly, a MonoBehaviour does not have a vessel; and secondly, that the expression does not refer to the active vessel (as specified by your question) but instead to the vessel to which a given module is attached. In other words, the expression will "follow" the vessel with the part, and not the player's focus.
Apart from that—I can't seem to find a Vessel.name in the 1.10 API docs, so I'm not sure if it's valid. After reading the API docs a bit more, I'd suggest using GetDisplayName() instead of either name or (as I suggested earlier) GetName(), since in some circumstances GetName() may return a localization token—this is almost certainly not what you're after if you're asking for a vessel's name.

On 7/24/2020 at 1:00 PM, Aniruddh said:

I got the resource consumption working (to some extant), here's the syntax for anyone who doesn't already know how to:


using System.Threading
 
int EChash = "ElectricCharge".GetHashCode();
Vessel objVessel = new Vessel();
objVessel.GetConnectedResourceTotals(EChash, out double amount, out double maxAmount, true);
Thread.Sleep(1000);
objVessel.GetConnectedResourceTotals(EChash, out double amount2, out double maxAmount2, true);
double ECperSecond = amount2 - amount;

This tells you EC consumption/usage per second.

There are a few "best practices" violations in this snippet, though as far as I know this is (approximately) the best way to do this kind of thing. I haven't worked with resources for a while, though, so I'm not an authority on that part.

Anyways:
Thread.Sleep() is not the correct way to do this, for several reasons—not the least of these being that Thread.Sleep() operates in real time, not game time. (If you've ever seen the clock turn red, you know how different these two can be.) Better to put this in a FixedUpdate() (of one of those MonoBehaviour or Part/VesselModules mentioned earlier), and use Time.fixedDeltaTime to get the length of the last physics frame. Note also that we're not using Update() and deltaTime because we expect changes to resources to happen in lockstep with the physics, not the rendering.
Rather than getting a read on the resource totals, and then waiting, and then getting another one, you can instead do the following:
1. Read the resource totals; place this in currentAmount.
2. Subtract lastAmount from this, and multiply divide by Time.fixedDeltaTime. This is the rate: the change multiplied by the time it took to make that change.
3. Put currentAmount in lastAmount to use next frame.

Edited by 0111narwhalz
Link to post
Share on other sites
14 hours ago, 0111narwhalz said:

2. Subtract lastAmount from this, and multiply by Time.fixedDeltaTime. This is the rate: the change multiplied by the time it took to make that change.

@Aniruddh

Just a little correction. If you want a rate, than you need to divide an amount by a time.

Link to post
Share on other sites

Ok, so my plugin is working as it should, no bugs which is great. I'm having problems with getting resource production, it gives a value of 0 when the resources are full. I know why this is happening, but I can't figure out what kind of algorithm I need to fix this. Does the game in any way track the resources produced in excess, or does it just throw it away?

Thanks for helping me out so far. I'm thinking of releasing the plugin publicly on these forums, as I think others may like it as well. :) 

Edited by Aniruddh
Figured out saving/loading from savefile
Link to post
Share on other sites

How do I get a list of all vessels in the current save file, active or not. I tried FlightGlobals.Vessels, but FlightGlobals.Vessels.Count always returns 0, implying there are no vessels even though there should be 2 vessels. Is that a bug in the stock game or is that an incorrect method? I'm running 1.10.1.

Edited by Aniruddh
Link to post
Share on other sites
16 minutes ago, Aniruddh said:

FlightGlobals.Vessels.Count always returns 0

In which scene did you test this because FlightGlobals.Vessels sure has all the vessels in the flight scene.

Link to post
Share on other sites
1 minute ago, sarbian said:

In which scene did you test this because FlightGlobals.Vessels sure has all the vessels in the flight scene.

I did test this in flight scene. However,  because of an if condition the rest of my code wont run until FlightGlobals.Vessels.Count returns int greater than 0. Btw, the log file shows nothing out of the ordinary.This was working a few days back, suddenly doesn't anymore.

Link to post
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...