Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

I'm kinda thinking along the lines of when you right-click on a vessel and select as target. Instead I'd just like to "target" a given surface coordinate.

I want to say I've seen something similar in the MJ code. Let me have a look... Here we go. That sounds like exactly what you're after (read comment).

Link to comment
Share on other sites

Hi, people. I'm aware that with KSP updates, plugins can break and it seems that somewhere in the update process, a code that my plugin used in previous versions doesn't work any more. An example of the basic idea of the code is this:


if(partActive == true)
{
if(this.part.RequestResource("Resource", -2 * TimeWarp.deltaTime) > 19.99)
{
partActive = false;
}
else
{
partActive = true;
}
}

The idea here is that when the amount of "Resource" reaches 20, the part will deactivate (and stop gathering the resource). However, this doesn't seem to work anymore in 0.23. It just gathers the resource until you manually deactivate the unit, which is no good if it is essential that it cannot gather any more of "Resource" when it hits 20. Any ideas, anyone? Thanks. :)

Umm, that's not how I parse that code snippet you posted. (Disclaimer: I have not worked with resources at all.)

What I see your code doing is checking if that part generates 20 or more resources on a game tick (as defined by Time Warp).

It looks like you do generate 2 resources a tick at 1x timewarp , so at a timewarp of less then 10 the part should be active, at a time warp of 10x or greater, the part will be disabled.

I see nothing about an "up to 20" check in that code.

D.

edit: Err, also a problem with the negative sign. As written, "-2 * TimeWarp.DeltaTime" will always be negative, and so always less then 19.99

Edited by Diazo
Link to comment
Share on other sites

Hi, people. I'm aware that with KSP updates, plugins can break and it seems that somewhere in the update process, a code that my plugin used in previous versions doesn't work any more. An example of the basic idea of the code is this:


if(partActive == true)
{
if(this.part.RequestResource("Resource", -2 * TimeWarp.deltaTime) > 19.99)
{
partActive = false;
}
else
{
partActive = true;
}
}

The idea here is that when the amount of "Resource" reaches 20, the part will deactivate (and stop gathering the resource). However, this doesn't seem to work anymore in 0.23. It just gathers the resource until you manually deactivate the unit, which is no good if it is essential that it cannot gather any more of "Resource" when it hits 20. Any ideas, anyone? Thanks. :)

Yes, the method changed behaviour in .23. What you could do instead could be this:

if (part.Resources["name"].amount >= 20) { //Deactivate }

to check when you must deactivate it. I believe that should work.

Link to comment
Share on other sites

Yes, the method changed behaviour in .23. What you could do instead could be this:

if (part.Resources["name"].amount >= 20) { //Deactivate }

to check when you must deactivate it. I believe that should work.

Thank you very much, I think that's fixed it! :D

Link to comment
Share on other sites

So I may be missing something obvious, but when I have a ShipConstruct (which we shall call "ship" for our purposes) and do something like ConfigNode shipNode = ship.SaveShip(); followed by ship2.LoadShip(shipNode); the loaded ShipConstruct is null. So I seem to be missing a step when loading from a ConfigNode. I can get around the issue by saving temporarily to a file

 
ship.SaveShip().Save(tempFile); //Saves as a ConfigNode, then saves the ConfigNode to a file
ship2 = ShipConstruct.LoadShip(tempFile); //Loads a ship from a file

But loading the file as a ConfigNode and then trying ship2.LoadShip(shipNode) results in the same issue. ConfigNode.LoadObjectFromConfig(ship2, shipNode) also results in nothing useful.

So I suppose my question is, does anyone know how to properly load a ShipConstruct from a ConfigNode generated by saving a ShipConstruct with ship.SaveShip()? If not, I'll keep using my temporary file method, but it seems like a backwards solution.

Link to comment
Share on other sites

[..]followed by ship2.LoadShip(shipNode); the loaded ShipConstruct is null.

This is what i don't get. ShipConstruct is a class and you call a member/method, so ship2 cannot' be null. Not before you call it (or you get a NullReferenceException... but you would ofc have mentioned that) and the call can't change that. Yes, you have to create the ship2 = new ShipConstruct() yourself before calling LoadShip! Apart from that should LoadShip(cfgNode) return a bool to indicate whether the call was successful and should log errors in case it was not.

Link to comment
Share on other sites

@Faark

I feel incredibly silly. I was actually loading the ship into the original ShipConstruct ship which is a member of my BuildListVessel class and apparently never thought to actually instantiate that (since one constructor takes it directly from the Editor and the second constructor, which is used when reading from the persistence, doesn't have access to that). I was getting NullReferenceExceptions with what I was doing (hence me saying it was null, but I was apparently thinking the wrong thing was null), so I should have probably mentioned that more explicitly. In short, I'm silly for not realizing my issue, so thank you for catching it for me.

Edit: Also, I can't give you more rep yet, darn :/

Link to comment
Share on other sites

Hi. Another little question on resources. I was writing my plugin, when it occurred to me that

part.Resources[""].amount

only checks the amount of a resource in that part. I was wondering if there is a way to check the whole vessel, as "vessel.Resources" doesn't seem to exist.

Thanks in advance. :)

Link to comment
Share on other sites

Hi. Another little question on resources. I was writing my plugin, when it occurred to me that

part.Resources[""].amount

only checks the amount of a resource in that part. I was wondering if there is a way to check the whole vessel, as "vessel.Resources" doesn't seem to exist.

Thanks in advance. :)

Short answer is no, there's no ship wide API object you can call.

You have to iterate through the Vessels parts property and collect the resource amount from each one and store them in your own variable.

Link to comment
Share on other sites

Sorry if this is a dumb question but if I'm trying to make a part plugin like this what do I reference to get PartModule?

Thanks.

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

namespace Plugin
{
public class PluginPart : PartModule
{
public override void OnStart(StartState state)
{
Debug.Log("Part awake");
}

public override void OnTriggerEnter(Collider other)
{
Debug.Log("Part collision");
}
}
}

Link to comment
Share on other sites

@SnappingTurtle

Your class derives from PartModule, so for non-static methods as shown above, this.vessel and this.part is what you are most likely looking for. Though in c# it is fine to cut off "this." and just write vessel, part, etc... in your methods.

Link to comment
Share on other sites

Okay. Time for what I'm hoping is an easy question.

I'm looking to call the force value of lift from atmospheric forces during flight as a number.

Or more simply, how much lift force are my wings giving me? Returned as a number so I can plug it into my thrust calculation.

I've been looking around trying to find out how to calculate this and I've made exactly zero progress. I've checked several other mods and was not able to find if they are calculating lift.

The only real lead I had was that the Object Browser in Visual Studio told me there was a CenterOfLiftQuery.lift value available, but from a Developer's post back in 2012 that query is available only in the editor.

So, I'm currently stuck at square one and don't even know how to start.

I'm not trying to edit wings or generate lift or anything, I simply want to know at this instant, how much lift force is being generated from the atmosphere?

Anyone have any ideas?

D.

Link to comment
Share on other sites

Short answer is no, there's no ship wide API object you can call.

You have to iterate through the Vessels parts property and collect the resource amount from each one and store them in your own variable.

Sorry, I don't quite understand how I do that. I thought I could search for the part I needed to check the resources for using vessel.Parts[] but this seems to refer to an integer, not a string, so I can't search for the part name. I only really have a basic knowledge of c# so any help would be really appreciated.

Link to comment
Share on other sites

Sorry, I don't quite understand how I do that. I thought I could search for the part I needed to check the resources for using vessel.Parts[] but this seems to refer to an integer, not a string, so I can't search for the part name. I only really have a basic knowledge of c# so any help would be really appreciated.

By using for and foreach loop, you can easily loop through the parts of a vessel and find the one you need. But if you want to simply refer to the prrt on which the module is, you can simply use this.part. Else, something like this could do:

List<Part> partsWithResource = new List<Part>();

foreach (Part p in vessel.parts)
{
if (p.Resources.Contains("ResourceName")) { partsWithResource.Add(p); }
}

Thanks Chris. Can you help me further? I can't figure out where to define behaviour for a trigger collision with another rigidbody.

Not off the top of my head, but I believe the Unity forums must be filled with questions like this. A short google should bring the answer.

Link to comment
Share on other sites

Is there any way to bring up a science experiment through my own method? I wanna be able to do all my conditions then execute science on my own method; complete with the ability to store, transmit and recover. I don't want to just do science += x.

Link to comment
Share on other sites

By using for and foreach loop, you can easily loop through the parts of a vessel and find the one you need. But if you want to simply refer to the prrt on which the module is, you can simply use this.part. Else, something like this could do:

List<Part> partsWithResource = new List<Part>();

foreach (Part p in vessel.parts)
{
if (p.Resources.Contains("ResourceName")) { partsWithResource.Add(p); }
}

Thanks, that's really helpful! :D

Link to comment
Share on other sites

Is there any way to bring up a science experiment through my own method? I wanna be able to do all my conditions then execute science on my own method; complete with the ability to store, transmit and recover. I don't want to just do science += x.

Search for mods that use IScienceDataContainer instead of ModuleScienceExperiment. Using the former you can control experimental conditions, which report you collect, the value, what happens when you push the buttons on the science report window etc... Everything that uses it has the same general format, so checking any of them should give you an idea of how to setup your own plugin.

Link to comment
Share on other sites

Search for mods that use IScienceDataContainer instead of ModuleScienceExperiment. Using the former you can control experimental conditions, which report you collect, the value, what happens when you push the buttons on the science report window etc... Everything that uses it has the same general format, so checking any of them should give you an idea of how to setup your own plugin.

You can also just add your experiment results to the stock ModuleScienceContainer, and avoid having to deal with any details. I also found that that approach allows truly generating science gradually, by adding a report with 0 data in it first, and then incrementing the value every frame until it reaches the full amount.

Link to comment
Share on other sites

Here's code from my proof-of-concept mod for generating science when flying planes and driving rovers: https://github.com/angavrilov/ksp-surface-survey/blob/master/SurfaceSurvey.cs#L276

I'm a little bit confused by how I can access the container class for use in-game. AddData also always throws an NullReference. Am I missing something here? :(

EDIT: Nevermind! I didn't think to add the ScienceContainerModule thing to the part itself. Works beautifully. Are you okay if I copy or break this code down and make my own rough version?

Edited by theSpeare
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...