Jump to content

Project Ground Anchor AKA: Please help me I don't know what I'm doing...


Recommended Posts

I'm trying to do my first plugin, it kinda works like I want it but not quite.

I'd like to make a module that when triggered in some way anchors the part its on to it's current position. But only if the part is close (1-2m max) to the ground and the vessel doesn't move.

So far I managed to set up Mono, and make a dll with a module and add that to a part.

This is my code:


using System;
using UnityEngine;


public class GroundAnchor : PartModule
{

/*
* This event is active when controlling the vessel with the part.
*/
[KSPEvent(guiActive = true, guiName = "Activate")]
public void ActivateEvent ()
{
ScreenMessages.PostScreenMessage ("Anchored", 5.0f, ScreenMessageStyle.UPPER_CENTER);

FixedJoint fj = this.part.gameObject.AddComponent<FixedJoint>();
fj.breakForce = Mathf.Infinity;
fj.breakTorque = Mathf.Infinity;

// This will hide the Activate event.
Events ["ActivateEvent"].active = false;
}
}

As you see, I'm not doing much at the moment. I've got the activate by right click stuff from the TAC Examples which works as advertised. I removed much of it because I need my module to work only once. I create a fixed joint on my part and set it to be unbreakable, I do not set a part to be joined to so it will join me to the world instead.

I still need to implement the close enough to ground and speed checks though, and I don't know how I would go about that. But the bigger problem for the moment is that my anchor stops anchoring on quickload. I assume it will do that whenever the vessel is loaded.

I figure I need to save the joint somehow (I assume adding a member variable to my class will do?) and reapply it on vessel load. How do I do that?

Link to comment
Share on other sites

You need to take advantage of OnStart and OnFixedUpdate.

And also use KSPField to make things Persistent.

right now you have everthing to activate when player pushes the button, so when the player changes screens or loads something else and goes back, you function is wiped and never restarted.

Better way would be to have the Button to active a KspField (like a bool)

Example

[KSPField(isPersistant = true)]

private bool activateAnchor = false;

Then use OnStart()

if (activateAnchor != false)

{

ActivateEvent();

}

then onFixedUpdate()

{

if (activateAnchor != false)

activateEvent()

}

What this does is KSPField keeps ActivateAnchor persistant at all times.(Saves it under the part in player save file)

OnStart keeps you Fuction alive if the player leaves vessel or comes back and part activate again (only ever checks once)

onFixedUpdate is the initial start of your function when player starts it from a cold state. (checks each FXframe)

Then you have your function an actual separate value in code and not part of KSPEvent instead have your bool activated by push GUI Button.

It might be argued that you don't need the Onstart() part, because KSPField and OnFixedUpdate should be all you need, but since what you seem to be writing is a lockdown code, I would argue you want to make sure it always work no matter what the player does. Leaves game, switches around to other vessels. You can try it without and test it for yourself.. Since OnStart() only does check once its not to much of a big deal for such small code.

you also want to shut off your code, when the player is done using it. All you need is another button to Turn it off and set bool false.

Edited by malkuth
Link to comment
Share on other sites

best bet is to forget about the distance to ground.. You can do it but its a little more complicated (not much) and your going to have to do a little math.

what you want is maybe just to make sure the vessel is landed so you can use that. (its already made for you) This is a value in vessel.situations that can give you status of ship, one of them is landed. So vessel.situations.landed will tell you when your vessel is landed on dry ground.

so look something like this, you can modify it to work with what ever you want. You want to intiate vessel. so.

Vessel vs = new Vessel(); or parameter CodeName(Vessel v)

Then the code as check

if (vs.situation.Equals(vs.situations.landed)

{

Place code.

}

this does not need to be persistent because you only need to check once, when player pushes GU Button. You might want to have an Else that gives a message that vessel is not landed (in case its not).

Otherwise if you want to use the height above ground you will have to do calculations, and I know of 2 Mods that do this. MechJeb and Kerbal engineer. But they most likely use.

Vessel.heightFromTerrain which gives you height above terrain, Vessel.altitude give you height above sealevel.

then you can do your maths for 2 meters part. Also if you want height with Part, and not the vessel you will have to do a little more work to make that happen too, right now the above will only apply to the actual vessel, and no an individual part.

Edited by malkuth
Link to comment
Share on other sites

Thanks again, I was messing around and found the part.checkLanded() method. It seems to return true when a part itself touches the ground.

It's close enough for what I want. I use it on each frame to enable or disable the GUI event. It seems to work good enough, there might be some cases where this fails, will test that later, a second check in ActivateEvent() should not be the big problem. Might even be better that way because I can better communicate to the user like that...

As for the originally planned height above terrain, I really only wanted to test for really close distance to ground, so I was thinking about casting a ray and see if I hit ground or something. However I discovered a problem with the whole approach, if I anchor myself to nothing like this and no part of my vessel is touching the ground, the vessel will be set to flying state, it will therefore be deleted when you switch scenes or drive away from it. So It might be best to drop the whole Idea :P

This is my current code:

using System;
using UnityEngine;


public class GroundAnchor : PartModule
{


[KSPField(isPersistant = true)]
private bool anchorActive = false;


public override void OnStart(StartState state)
{
if ( anchorActive ) {
attachToGround();
}
}


public override void OnUpdate()
{

if ( this.part.checkLanded() && !anchorActive) {
Events ["ActivateEvent"].active = true;
} else {
Events ["ActivateEvent"].active = false;
}
}

/*
* This event is active when controlling the vessel with the part.
*/
[KSPEvent(guiActive = true, guiName = "Activate")]
public void ActivateEvent ()
{
ScreenMessages.PostScreenMessage ("Anchor fired", 5.0f, ScreenMessageStyle.UPPER_CENTER);

attachToGround();
anchorActive = true;

Events ["ActivateEvent"].active = false;
}

private void attachToGround ()
{

FixedJoint fj = this.part.gameObject.AddComponent<FixedJoint>();
fj.breakForce = Mathf.Infinity;
fj.breakTorque = Mathf.Infinity;
}

}

I think it's pretty ok, but please point out problems if you see any.

Thanks.

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