Jump to content

KSPAchievements and ProgressNodes


Recommended Posts

I'm looking at the OnProgressReached event in order to see when KSPAchievements are reached.

Is there any real documentation on it?  Specifically, I'd like to know what achievement was reached when the event is thrown; it's not obvious to me (yet) how to follow the ProgressNodes to get what I need.

Thanks

Link to comment
Share on other sites

Do you mean info about which achievements have already been reached (it's all stored in the save file), or info about an achievement as it is reached?

For one thing, there are three separate progress events, Reached, Completed, and Achieved.

Reach is for when you first access a set of progress nodes, like the first speed achievement, or the first node for a celestial body.

I think complete is for any progress node on the first time you complete it, so the first time you orbit around a specific planet, or the first time you plant a flag.

And I think achieve is fired any time you finish a progress node, even if it has been done before; you won't get any rewards or messages for this.

To figure out the type of achievement for any of those events you'll need to take the ProgressNode class returned and figure out which one of its derivative classes it belongs to; each node has a string ID that can be used to tie it to its derivative class.

It's all sort of a pain, and basically requires manually handling each different progress node type. But it's all been done before if you want to look through it: https://github.com/DMagic1/KSP_Progress_Parser/tree/master/Source

Link to comment
Share on other sites

On 7/18/2017 at 10:19 AM, DMagic said:

You can take whatever you need, or if it's suitable you can use it as a dependency, it is very infrequently updated.

I'm trying to figure out how to use it as a dependency, rather than copying code.

Basicly, I have the OnProgressReached and OnProgressComplete events set up, I need to get the text that is added to the flight log so I can include it. Is there an easier way?  or how can I interface with this? 

Link to comment
Share on other sites

5 hours ago, JPLRepo said:

The public API contains lots of information these days.
https://kerbalspaceprogram.com/api/index.html

in a very non-intuitive format.  Many things don't have any descriptions, etc.  Sometimes it even make things harder, since it appears there is something, but no idea how to use it.

I'll get it figured out, but was looking for a little help to save some time.

I need to get the data, probably at the same time it's being added (using the same gameevent), which makes things harder.  There is a good change that my code would run before the new data is added to the log.

Edited by linuxgurugamer
Link to comment
Share on other sites

Do you mean the message that pops up in the little notifications window? I don't think that is stored or accessible in any way. You just have to find the relevant message in the localization files and refer to that. 

ProgressParser does that a lot, just manually assigning strings for each node type, that's part of why it's so tedious. I think each progress node should have it's associated message stored. On mobile so I can't link the exact location.

To go over it a little more:

There are a few things about progress nodes worth knowing.

KSP initializes all of the progress nodes whenever a scene loads, then it parses the save file to see which are completed, or what state they are in. After this happens is when Progress Parser loads everything.

The descriptions for all of the different nodes are manually loaded (you can't use the localizer method in a field initialization, so the localization tags have to be processed at some point), using strings from the localization file (most are in the same place in the file, and are pretty obvious).

There are two basic types of nodes, interval nodes for the things like speed, altitude, etc... records, where one node stores each of the threshold values and their completion state. And the standard nodes, there are the basic ones like first launch or reach space, then the POI nodes for anomalies, then a set of nodes for each celestial body, like orbit, land, plant a flag, etc... (with a slightly different set for the home planet).

All of Progress Parser's info on nodes can be accessed through various methods and properties found at the bottom of the ProgressParser static class.

For the standard nodes the completion message can be accessed using the ProgressStandard.Descriptor string. Some of them require the name of the celestial body, and the POI nodes require some different handling, Contracts Window Plus has an example of how they should be used to actually display the string.

For the interval nodes you have to get how many intervals are available and which have been completed, along with the message string and the actual value and units for each interval (like 200m/s, 500m/s 1000m/s, etc for the speed rewards).

Progress Parser updates all of its values for interval nodes every time one of the Progress Node events (reach, achieved, or completed) is fired. For the standard nodes they are only updated when the OnComplete event is fired (since the reach and achieve events don't really apply to these).

I think what you need is all there. It's all loaded on a scene change, so all you need to check when an event fires is whether or not a certain progress node is actually finished. The event fires after the node is processed, so everything should be up to date by the time Progress Parser gets to it.

Edited by DMagic
Link to comment
Share on other sites

Ok, I'm getting a bit of an understanding here.

I'm having a problem in that a number of methods are private, and I'm having to duplicate them, I'd rather not if possible, and I don't really want to use Reflection.

Would you consider making some of them public in a new release?

Basicly, I need to duplicate the onComplete() and onReach() methods, and they call a number of private functions, all apparently in the progressController class.

If you are, I can make the changes I need and push a PR  to you on Github.  The changes would ONLY be changing some methods from private to public

Let me know.

Edited by linuxgurugamer
Link to comment
Share on other sites

Why do you need them public? They are private because they are only called by the events, and the events are fired whenever something related to the progress nodes is changed. If they need to be called then it should probably be by firing the event.

The other associated methods could be made public, though those are really just simple utilities, like checking which kind of progress node it is, or pulling some value out of the node (which is more complicated than it should be because of how the fields in progress nodes are so inconsistent :huh:).

To be clear, I have no problem with making them public, I'm just confused about why.

Edited by DMagic
Link to comment
Share on other sites

8 minutes ago, DMagic said:

Why do you need them public? They are private because they are only called by the events, and the events are fired whenever something related to the progress nodes is changed. If they need to be called then it should probably be by firing the event.

The other associated methods could be made public, though those are really just simple utilities, like checking which kind of progress node it is, or pulling some value out of the node (which is more complicated than it should be because of how the fields in progress nodes are so inconsistent :huh:).

I don't need the onComplete() or onReach() public.  I'm writing those myself in my mod.

What I need are the following, I've done this on a fork:

public double getIntervalRecord(ProgressNode n)
public bool isIntervalType(ProgressNode n)
public bool isPOI(ProgressNode n)
public CelestialBody getBodyFromType(ProgressNode n)

and, for myself, I've added the following minor change to the getIntervalRecord():

public double getIntervalRecord(ProgressNode n)
{
	string descr = "";
	return getIntervalRecord(n, ref descr);
}

public double getIntervalRecord(ProgressNode n, ref string descr)
{
	Type t = n.GetType();

	if (t == typeof(RecordsAltitude))
	{
		descr = "Altitude";
		return ((RecordsAltitude)n).record;
	}
	else if (t == typeof(RecordsDepth))
	{
		descr = "Depth";
		return ((RecordsDepth)n).record;
	}
	else if (t == typeof(RecordsDistance))
	{
		descr = "Distance";
		return ((RecordsDistance)n).record;
	}
	else if (t == typeof(RecordsSpeed))
	{
		descr = "Speed";
		return ((RecordsSpeed)n).record;
	}
	descr = "";
	return 0;
}

 

Link to comment
Share on other sites

That's fine. Though everything in Progress Parser is localized, so I would probably want to use the localized names for the descriptions (there isn't a stock translation for depth, but I have a few translations that I need to add in the next update) instead of the hard-coded values.

Link to comment
Share on other sites

I think what @DMagic said. And please don't talk about private methods or de-compiling. It's against the rules. I don't believe you need anything not public.
The public API documentation has some information. Anyone who can read the public API can usually figure it out.
There are gameevents for the progress events.
There is the ProgressTracking scenario with plenty of public information.
 

Link to comment
Share on other sites

3 hours ago, DMagic said:

That's fine. Though everything in Progress Parser is localized, so I would probably want to use the localized names for the descriptions (there isn't a stock translation for depth, but I have a few translations that I need to add in the next update) instead of the hard-coded values.

Ok.  Once I have everything working, I'll submit a PR.  I haven't gotten into the localization, but it's only 4 lines, so I suppose it won't be that difficult to find

Link to comment
Share on other sites

Except for depth they are already handled KSP has the translations in stock, distance has to be modified since all I could find was a string with Distance: <<1>>, but I just take the substring before the :, I tested it with all of the stock languages and it works fine, including with the languages that use the slightly different colon character. 

Link to comment
Share on other sites

@DMagic

I'd like to thank you for your help.  With your explanation and patience, I have it working.

I'm going to take the posts  you did earlier and put them together in a document, I'll include that in the PR I'll be submitting to you.  I hope it will be helpful for others.

Link to comment
Share on other sites

23 hours ago, linuxgurugamer said:

I was talking about private methods in the ProgressParser mod.  And I didnt say a word about decompiling.

Oh sorry. Victim of casually reading through vast quantities of posts while working.
My bad.

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