Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

@EladDv: Yikes, there are several issues with your code and they are bad enough I can't actually parse what you are trying to do with this.

My comments in line:

  partConfig.Save(KSPUtil.ApplicationRootPath+ "\\EladsConfig.cfg"); //Okay, you are saving the partConfig configNode to disk at that file location.         
Part FinalPart = ConfigNode.CreateObjectFromConfig<Part>(partConfig) ; //making a new part FinalPart from the partConfig configNode. You sure this is a valid part configNode? I see no error checking or null checking to make sure this worked.
//ConfigNode.LoadObjectFromConfig(FinalPart, partConfig);
List<PartResource> newList = new List<PartResource>(); //make a new list of Resources, alright.
foreach (ConfigNode node in TotalResources) //cycle through the TotalResources list, but as ConfigNodes? That seems odd but as you don't post your code where you populate TotalResources I can't comment further.
{
Debug.Log(" creating resources ");
PartResource res = new PartResource(); //make a new resource called res
string resourceName = node.GetValue("name");
double resourceAmount = double.Parse(node.GetValue("amount"));
double resourceMax = double.Parse(node.GetValue("maxAmount"));
res.resourceName = resourceName;
res.amount = resourceAmount;
res.maxAmount = resourceMax;
FinalPart.Resources.Add(node); //you are adding the raw node to FinalPart? You sure this works? Resources is a list of PartResource objects, not ConfigNode obejcts.

//something is missing here, you made the res Resource but you just hit the end of the method where you created it without saving it, you hit this close bracket the res object gets sent to garbage collection to be destroyed.
}
Debug.Log(" created resources ");
Debug.Log(" Created Part ");
Debug.Log(" Part mass " + FinalPart.mass);
Debug.Log(" Part Name " + FinalPart.partName);
return FinalPart;

So ya, I can't actually tell what you were trying to do. Notable the 'res' resource object isn't actually doing anything.

@NathanKell: The issue with ForEach being a bad option in Unity is only true if you use Unity's built-in compiler. If you use a recent compiler, such as Microsoft's Visual Studio, there is no issue with ForEach.

@Commander Jebidiah: You'd have to run code that compared current temperature of a part to that part's maxTemp, then trigger the alarm via a .playSound object. Exactly how depends on what you are doing, just heatshield parts? Probably would use a PartModule. Every part on the loaded vessel? Probably use a KSPAddon.Flight class to do so.

D.

Edited by Diazo
Link to comment
Share on other sites

@EladDv: Yikes, there are several issues with your code and they are bad enough I can't actually parse what you are trying to do with this.

My comments in line:

  partConfig.Save(KSPUtil.ApplicationRootPath+ "\\EladsConfig.cfg"); //Okay, you are saving the partConfig configNode to disk at that file location.         
Part FinalPart = ConfigNode.CreateObjectFromConfig<Part>(partConfig) ; //making a new part FinalPart from the partConfig configNode. You sure this is a valid part configNode? I see no error checking or null checking to make sure this worked.
//ConfigNode.LoadObjectFromConfig(FinalPart, partConfig);
List<PartResource> newList = new List<PartResource>(); //make a new list of Resources, alright.
foreach (ConfigNode node in TotalResources) //cycle through the TotalResources list, but as ConfigNodes? That seems odd but as you don't post your code where you populate TotalResources I can't comment further.
{
Debug.Log(" creating resources ");
PartResource res = new PartResource(); //make a new resource called res
string resourceName = node.GetValue("name");
double resourceAmount = double.Parse(node.GetValue("amount"));
double resourceMax = double.Parse(node.GetValue("maxAmount"));
res.resourceName = resourceName;
res.amount = resourceAmount;
res.maxAmount = resourceMax;
FinalPart.Resources.Add(node); //you are adding the raw node to FinalPart? You sure this works? Resources is a list of PartResource objects, not ConfigNode obejcts.

//something is missing here, you made the res Resource but you just hit the end of the method where you created it without saving it, you hit this close bracket the res object gets sent to garbage collection to be destroyed.
}
Debug.Log(" created resources ");
Debug.Log(" Created Part ");
Debug.Log(" Part mass " + FinalPart.mass);
Debug.Log(" Part Name " + FinalPart.partName);
return FinalPart;

So ya, I can't actually tell what you were trying to do. Notable the 'res' resource object isn't actually doing anything.

D.

First I'd like to say thanks for the detailed look.

The config node partConfig i am creating the new part from is never null and always valid- at least in that test case (if i can get it to work in one case i will put more checks but currently i see no reason why)

TotalResources is just the confignodes of all the resources i added to the part (that's after combining amounts) that part is good-as i can get the resource count to be right if i check it.

the res object is a remnants from an earlier iteration where i accessed the FinalPart.Resources.list directly and tried to add in the resources that way-it serves no purpose in this iteration and i should comment it out but it's nice to have there in case i need it.

part.Resources.add and part.AddResources take only a config node as their argument and are basically the same function(the latter is calling the first), and what they do is basically get the node and convert it to a part resource(what i did with res) and add it to the list(i tried to do that with res as well but it returned NRE) my main suspicion is that it somehow initializes the part with a null Resources field and then because it's read only it prevents me from setting it-i have tried to poke inside with bindingflags but to no avail.

i could go around that problem by copying another part into FinalPart and change it's values to the desired ones(sadly LoadObjectFromConfig dosnt work in that case very well) but that's really ugly and i would rather use it as last resort.

Link to comment
Share on other sites

Fengist:

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


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

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

Thanks Nathan! Worked great. I had to make some modifications due to flawed logic but it works as intended. I had to set the intakes to enabled=false as well as closing them otherwise you could manually reopen them. Just in case you're curious as to why I need to do this, I'm working on a submersible with electric engines. It'll also have a near 0 thrust LF engine with an alternator on it to recharge batteries. I could have used ModuleGenerator to accomplish the same thing, but the smoke and sounds from a ModuleEngine is what I wanted but I didn't want it to be usable when submerged.

As for the engines, didn't work as intended. I tried changing various settings and nothing I found really worked with both stock and mods. What I settled on was:

        if (FlightGlobals.ActiveVessel.altitude > 2.0)
{
//Debug.Log("[Maritime Pack]Shutting Down Engine");
FlightGlobals.ActiveVessel.ctrlState.mainThrottle = 0;
}

Which works. Get above 2m and the throttle drops to 0, get below 2m and it magically goes back to where you had it.

Thanks again.

Link to comment
Share on other sites

Next question: And I know not many people have worked with the camera in KSP so... here goes.

I'm working with some old code from Hooligan Labs Sub mod. After much hacking, I have a camera that works underwater. The problem: Unlike the surface camera which stops when it hits terrain, the code I have does not. It'll pass right through the underwater terrain. I'm trying to stop it from doing that by finding it's distance to the terrain.

I have tried this:


cameraAltitude = Terrain.activeTerrain.SampleHeight(UnderwaterCamera.ActiveFlightCamera.transform.position);

which leads to a nullref.

I've tried casting a ray downward from the camera like this:


RaycastHit hit;
if (Physics.Raycast(UnderwaterCamera.ActiveFlightCamera.transform.position, Vector3.down, out hit, 5000))
{
ScreenMessages.PostScreenMessage(new ScreenMessage("Camera Hit: " + hit.transform.name +" Distance: "+hit.distance, 3f, ScreenMessageStyle.UPPER_LEFT));
}

Which leads to some REALLY odd results. It seems that even when the terrain is 50m below the camera, the ray doesn't hit anything for several thousand meters.

I can get the altitude of the camera doing this:


cameraAltitude = findAltitude(UnderwaterCamera.ActiveFlightCamera.transform);

private static double findAltitude(Transform aLocation)
{
if (FlightGlobals.ActiveVessel == null) return 0;
return Vector3.Distance(aLocation.position, FlightGlobals.ActiveVessel.mainBody.position) - (FlightGlobals.ActiveVessel.mainBody.Radius);
}

But, that tells me the altitude from the surface of the water, not the actual bottom of the ocean, which when submerged, is a negative number.

I can get the vessel's distance to the terrain with this:


FlightGlobals.ActiveVessel.heightFromTerrain

But, there seems to be nothing like that for a camera.

Any ideas would be greatly appreciated. And pls keep in mind when explaining, I'm still a noob at this whole plugin thing.

Link to comment
Share on other sites

I run a raycast for actual vessel height in my Landing Height mod (in my sig) if you want to see the actual code, but there are several cases where I have to fall back to using the Vessel.HeightFromTerrain that you linked.

The two biggest issues are:

a) Deep underwater, there does not seem to be a PQS layer to hit with the raycast. I don't know if it's based of how far underwater, or how far from shore, but a large percentage of the ocean floor just doesn't exist.

B) The raycast return can get wonky when really close (<2meter) to ground. It seems to sometimes miss the top of the PQS terrain collider and return from the bottom edge of the PQS. This only causes errors in the 10 meter or so range though, nothing like you described.

For what you are doing, I think you are going to have to dive into the PQS stuff to do this correctly and that's not something I've ever dealt with so I can't offer any advice on it.

D.

Link to comment
Share on other sites

Hello all. I'm new to C# and Unity, so this question may be rather basic.

I'm starting a small mod and trying to add a few new fuels for some specialty engines. I think I've got the .cfg file format down, but I haven't figured out how to tell the game to load my .cfg file to make the resource available. I've looked through the CRP files, tried reading the API documentation on PartResourceDefinition to try define the resource directly in C#, and tried searching this thread (that just game me posts of people doing odd things with fuel), but I can't figure it out.

My "coding" experience is mostly with number crunching, so this is rather different.

Link to comment
Share on other sites

Hello all. I'm new to C# and Unity, so this question may be rather basic.

I'm starting a small mod and trying to add a few new fuels for some specialty engines. I think I've got the .cfg file format down, but I haven't figured out how to tell the game to load my .cfg file to make the resource available. I've looked through the CRP files, tried reading the API documentation on PartResourceDefinition to try define the resource directly in C#, and tried searching this thread (that just game me posts of people doing odd things with fuel), but I can't figure it out.

My "coding" experience is mostly with number crunching, so this is rather different.

Link to comment
Share on other sites

Trying to calculate the dimensions of a Vessel.

                                ShipTemplate scShip = ???;                                Vector3 vSize = ShipConstruction.CalculateCraftSize(scShip);

Easy enough if it was a ShipConstruction in the editor. It's a Vessel in the Flight Scene. I've hunted through what's available on Vessel and nothing seems to point to that Vessel's ShipTemplate.

Any thoughts on how I get a Vessel's ShipTemplate, so I can just use CalculateCraftSize, which is right bloody there to do what I want, calculate the size of a freakin craft.... ahem, excuse me.

EDIT - nm Occurs to me it couldn't handle docked craft anyway. I guess there's just the long way :D

Edited by AlphaAsh
Link to comment
Share on other sites

I posted this question in its own thread, but I'm posting it here too, because this thread seems much more active.

I have a plugin that spawns some gameobjects into the game. Unfortunately, they shift around whenever the floating origin shifts. Does anyone know how to shift them back when that happens.

I've tried using the GameEvents.onFloatingOriginShift event, but it does not appear to do anything.

I also tried checking the FloatingOrigin.Offset property every frame to see if it's changed, and it works, but there is still 1 frame where it's shifted before I can shift it back, which usually ends up with an object appearing inside my ship for a single frame and tearing it apart. :(

Edited by MrHappyFace
formatting
Link to comment
Share on other sites

I run a raycast for actual vessel height in my Landing Height mod (in my sig) if you want to see the actual code, but there are several cases where I have to fall back to using the Vessel.HeightFromTerrain that you linked.

The two biggest issues are:

a) Deep underwater, there does not seem to be a PQS layer to hit with the raycast. I don't know if it's based of how far underwater, or how far from shore, but a large percentage of the ocean floor just doesn't exist.

B) The raycast return can get wonky when really close (<2meter) to ground. It seems to sometimes miss the top of the PQS terrain collider and return from the bottom edge of the PQS. This only causes errors in the 10 meter or so range though, nothing like you described.

For what you are doing, I think you are going to have to dive into the PQS stuff to do this correctly and that's not something I've ever dealt with so I can't offer any advice on it.

D.

So far, my issue is getting the raycast to fire faster than the mouse can move. I've tried spherecast but it appears to ram into the camera itself. Thanks for the ideas tho, i'll look more into the pqs.

Link to comment
Share on other sites

Does anyone know how I can figure out what ship part is currently highlighted, i.e. under the cursor?

I can see in the debugger that there are two non-public bools that change state when the cursor hovers over a part, but they don't seem accessible, nor are their names readable (strange characters)

Link to comment
Share on other sites

How do I make a .cfg file for parts? And seperately, a .cfg file for resources.

Open Notepad or vi or TextEdit or whatever editor you like, and type it in :)

If you're looking for the structure, you can copy any of the parts from GameData\Squad\Parts to get started.

For resources, it's just:


RESOURCE_DEFINITION
{
name = CarbonDioxide
density = 0.000001951
flowMode = ALL_VESSEL
transfer = PUMP
isTweakable = true
unitCost = 0.0000028637
}

Please check the Community Resource Pack to make sure you're not creating a conflicting resource (and for lots of examples!)

Link to comment
Share on other sites

Thank you! I have it mostly sorted now, but I have another question! *Gasp!*

Theres a fuel flow thing in engine configs, and I've asked at #KSPModders and they don't know the setups for it, ATM the fuel flow mode for the engine is STACK_PRIORITY_SEARCH or something like that, what should I type in to change it to stage search?

Thanks.

Link to comment
Share on other sites

Thank you! I have it mostly sorted now, but I have another question! *Gasp!*

Theres a fuel flow thing in engine configs, and I've asked at #KSPModders and they don't know the setups for it, ATM the fuel flow mode for the engine is STACK_PRIORITY_SEARCH or something like that, what should I type in to change it to stage search?

Thanks.

The options are NO_FLOW (only resources on same part), ALL_VESSEL (anything on the vessel), STAGE_PRIORITY_FLOW (anything in the same stage), STACK_PRIORITY_SEARCH (anything stack connected in the same stage), and NULL (can't do anything).

Link to comment
Share on other sites

Correction: STAGE_PRIORITY_FLOW flows from anywhere on the vessel, same as ALL_VESSEL, it just preferentially draws from parts in earlier stages (so, e.g. if your initial stage has monoprop, and your upper stage has monoprop, and your payload has monoprop, RCS thrusters everywhere on the ship will first draw from the initial stage and suck it dry, then move on to the upper stage, and finally the payload).

Link to comment
Share on other sites

Ya gonna have to all get used to this real soon:

How do I UV unwrap in Blender? I go into edit mode, mesh, UV something, then UV unwrap, on one of my engine models it says in the top of the screen something about scale or something and doesn't do anything, on the other it does nothing but doesn't display an error.

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