Jump to content

[SOLVED] List of parts available to the player


Recommended Posts

Hello !

I'm trying to wrap my head around how it is possible to get the list of all parts available to the user in the VAB / SPH, especially in career mode (not on a ship/rocket/plane, but available to build one).

When you start a new career, you are limited to the number of parts available. You can unlock more parts by spending Science points in the R&D center, which then unlock new parts in the VAB / SPH depending on the chosen branches in the Tech tree.

While in the VAB / SPH I'm able to access all the parts loaded by the game:

        internal void Start()
        {
            Debug.Log("[TestPlug] Start");
            if (PartLoader.LoadedPartsList == null)
            {
                UnityEngine.Debug.LogError("[TestPlug]: No LoadedPartsList; Game not entirely loaded?");
                canRun = false;
                return;
            }
            else
            {
                canRun = true;
            }

            foreach (AvailablePart part in PartLoader.LoadedPartsList)
            {
                var logpart = string.Format("Name: {0} ; Title: {1}; Category: {2}", part.name, part.title, part.category);
                Debug.Log(logpart);

                foreach(AvailablePart.ResourceInfo resInfo in part.resourceInfos)
                {
                    Debug.Log(string.Format("    Resource name: {0}", resInfo.resourceName));
                }
            }
            // [snip]

Output example :

[LOG 17:40:08.557] Name: noseCone ; Title: Aerodynamic Nose Cone; Category: Aero
[LOG 17:40:08.558] Name: airbrake1 ; Title: A.I.R.B.R.A.K.E.S; Category: Aero
[LOG 17:40:08.559] Name: airScoop ; Title: XM-G50 Radial Air Intake; Category: Aero
[LOG 17:40:08.561]     Resource name: Intake Air
[LOG 17:40:08.562] Name: airlinerCtrlSrf ; Title: FAT-455 Aeroplane Control Surface; Category: Aero
[LOG 17:40:08.563] Name: airlinerMainWing ; Title: FAT-455 Aeroplane Main Wing; Category: Aero
[LOG 17:40:08.564]     Resource name: Liquid Fuel
[LOG 17:40:08.565] Name: airlinerTailFin ; Title: FAT-455 Aeroplane Tail Fin; Category: Aero
[LOG 17:40:08.567] Name: AdvancedCanard ; Title: Advanced Canard; Category: Aero
[LOG 17:40:08.568] Name: CanardController ; Title: Standard Canard; Category: Aero
[snip]

What I'd like is to access the list of all the parts available or shown in the VAB / SPH, depending on the tech tree of the player.

I have tried many things to actually get only the parts available / shown to the player in the VAB, but I haven't succeeded...  (like using the  ResearchAndDevelopment.PartModelPurchased() and other functions, but all my attempts failed).

I guess I should try something around  "EditorPartListFilter<AvailablePart>" but I don't know which filter I should use...

What do I need to do exactly?

Thank you !

Edited by neitsa
solved!
Link to comment
Share on other sites

Try:

var purchased = PartLoader.LoadedPartsList.Where(p => ResearchAndDevelopment.PartModelPurchased(p));

or

var partTechAvailable = PartLoader.LoadedPartsList.Where(p => ResearchAndDevelopment.PartTechAvailable(p));

 

Edited by Aelfhe1m
Added option
Link to comment
Share on other sites

Hi @Aelfhe1m , thank you for your answer !

Unfortunately, this doesn't work... :( They both (PartModelPurchased() and PartTechAvailable() function return value) are set to true for all parts, even if the tech is not available. I tested it in both Science and Carrer mode, and it works the same in both modes (all part set to True for purchased and Techavailable).

Here is a screenshot of a science mode play: http://imgur.com/yYmBp3Q

For example, the Cupola isn't available in the "pods" category (on the above screenshot), but the code still returns True. 

Below is a snippet of the output from the plug-in (with techAvailable and purchased, which are the return value of respectively PartTechAvailable() and PartModelPurchased()) :

[LOG 18:31:43.105] Name: cupola ; Title: PPD-12 Cupola Module; Category: Pods; techAvailable: True; purchased: True
[LOG 18:31:43.106]     Resource name: Electric Charge
[LOG 18:31:43.107]     Resource name: Mono Propellant
[LOG 18:31:43.108] Name: seatExternalCmd ; Title: EAS-1 External Command Seat; Category: Pods; techAvailable: True; purchased: True
[LOG 18:31:43.110] Name: crewCabin ; Title: PPD-10 Hitchhiker Storage Container; Category: Utility; techAvailable: True; purchased: True
[LOG 18:31:43.111] Name: advSasModule ; Title: Advanced Inline Stabilizer; Category: Control; techAvailable: True; purchased: True
[LOG 18:31:43.112] Name: sasModule ; Title: Small Inline Reaction Wheel; Category: Control; techAvailable: True; purchased: True
[LOG 18:31:43.113] Name: Mark1-2Pod ; Title: Mk1-2 Command Pod; Category: Pods; techAvailable: True; purchased: True
[LOG 18:31:43.115]     Resource name: Electric Charge
[LOG 18:31:43.116]     Resource name: Mono Propellant

Still wondering what is wrong or what I should do...

Anyway, thanks a lot for taking time to help me!

Edited by neitsa
typo + username
Link to comment
Share on other sites

46 minutes ago, neitsa said:

Hi @Aelfhe1m , thank you for your answer !

Unfortunately, this doesn't work... :( They both (PartModelPurchased() and PartTechAvailable() function return value) are set to true for all parts, even if the tech is not available. I tested it in both Science and Carrer mode, and it works the same in both modes (all part set to True for purchased and Techavailable).

That's odd. Just checked running this code in the VAB on a science mode game after unlocking the first two nodes:

var purchased = PartLoader.LoadedPartsList.Where(p => ResearchAndDevelopment.PartModelPurchased(p));
Debug.Log("Available parts:");
foreach (var p in purchased)
{
     Debug.Log($"Name: {p.name}, title: {p.title}");
}

result was:

[LOG 18:19:03.485] Available parts:
[LOG 18:19:03.485] Name: Engineer7500, title: ER-7500 Computer Flight Unit
[LOG 18:19:03.486] Name: EngineerChip, title: Kerbal Engineering System
[LOG 18:19:03.486] Name: basicFin, title: Basic Fin
[LOG 18:19:03.487] Name: mk1pod, title: Mk1 Command Pod
[LOG 18:19:03.487] Name: liquidEngine2, title: LV-T45 "Swivel" Liquid Fuel Engine
[LOG 18:19:03.487] Name: solidBooster, title: RT-10 "Hammer" Solid Fuel Booster
[LOG 18:19:03.488] Name: solidBooster.sm, title: RT-5 "Flea" Solid Fuel Booster
[LOG 18:19:03.488] Name: fuelTankSmallFlat, title: FL-T100 Fuel Tank
[LOG 18:19:03.489] Name: GooExperiment, title: Mystery Goo™ Containment Unit
[LOG 18:19:03.489] Name: science.module, title: SC-9001 Science Jr.
[LOG 18:19:03.490] Name: trussPiece1x, title: Modular Girder Segment
[LOG 18:19:03.490] Name: longAntenna, title: Communotron 16
[LOG 18:19:03.491] Name: stackDecoupler, title: TR-18A Stack Decoupler
[LOG 18:19:03.491] Name: parachuteSingle, title: Mk16 Parachute
[LOG 18:19:19.816] SCREENSHOT!!

Screenshot. 

The tests were done in 1.1.3 but the plugin DLL was compiled against the 1.1.2 binaries (haven't got around to updating the paths in VS yet).

Edit: I also tested on a career save and the part unlocking is taken into account correctly.

Edited by Aelfhe1m
Link to comment
Share on other sites

Hi guys!

Oh, btw I'm testing against KSP 1.1.3.1289

Sorry for the late reply and thank you @Aelfhe1m and @Crzyrndm very much for your answers!

@Aelfhe1m I tried your code both in Start() and Update() functions.

At first I tried once in the Update() function,  so I didn't have to execute the code each time the function is called. I simply put a boolean and once the function was executed, changed the boolean so I knew I had the whole list part.

I removed that boolean and am executing the code on each call to Update(). I'm still getting the whole list of parts until the user starts to search for a part: at that point the list seems to be filtered and I'm getting the right list of parts! (that is, the part that are only available to the player depending on his tech tree).

Executing the code on Start() or Update() without player interaction still gives me the whole part list (without any filtering).

  • Do you have the same behavior?
  • Do you know if it's possible to get the list of parts (depending on the player tech tree) without the player using the search box?

Thanks a lot!

Edited by neitsa
add KSP version
Link to comment
Share on other sites

Problem solved, finally :)

I'm not sure this is a good solution, but it works as intended.

What's clicked in my head was this log line (produced by KSP itself):

Quote

[ApplicationLauncher] OnSceneLoadedGUIReady: scene EDITOR ShouldBeVisible() True ShouldBeOnTop() False iIsPositionedAtTop False

Before this line, all calls to get user available parts (in the Update() function) returned `true` for all parts, but I could see that the parts were actually filtered after the above log message was displayed (which indicates that the VAB / SPH is fully loaded and the GUI is ready).

So I decided to wait for the GUI to be loaded, something along those lines:

internal void Start()
{
    Debug.Log("[Test] Start");
    if (PartLoader.LoadedPartsList == null)
    {
        UnityEngine.Debug.LogError("[Test]: No LoadedPartsList; Game not entirely loaded?");
        canRun = false;
        return;
    }
    else
    {
        canRun = true;
    }
    
    // callback fired when a level is loaded and the GUI is ready
    GameEvents.onLevelWasLoadedGUIReady.Add(new EventData<GameScenes>.OnEvent(OnSceneLoadedGUIReady));
    
    // snip            
}

The callback looks like this :

private void OnSceneLoadedGUIReady(GameScenes scene)
{
    Debug.Log("[Test] OnSceneLoadedGUIReady enter.");

    // loading scene: not interesting
    if (scene == GameScenes.LOADING)
        return;

    // check that the editor is loaded and ready
    if (scene == GameScenes.EDITOR)
    {
        Debug.Log("Editor ok");
        EditorLoaded = true;
    }

    Debug.Log("[Test] OnSceneLoadedGUIReady leave.");
}

and then in the Update() function:

internal void Update()
{
    Debug.Log("[Test] Update() : entering");

    if (EditorLoaded & !ListPartObtained)
    {
        // get all parts available to the player depending on his/her tech tree
        var purchased = PartLoader.LoadedPartsList.Where(p => ResearchAndDevelopment.PartModelPurchased(p));
        Debug.Log(string.Format("Available parts: [{0}]", callNum)); callNum++;
        foreach (var p in purchased)
        {
            Debug.Log($"Name: {p.name}, title: {p.title}, category: {p.category}");
        }
        
        // we got the list
        ListPartObtained = true;
    }

    updateDone = true;

    Debug.Log("[Test] Update() : leaving");
}

It might also be a good option to refresh the list each time the player enters the VAB / SPH.

Probably not a perfect solution, but it does the job :D 

Thanks a lot for your help!

Link to comment
Share on other sites

23 hours ago, neitsa said:

Before this line, all calls to get user available parts (in the Update() function) returned `true` for all parts, but I could see that the parts were actually filtered after the above log message was displayed (which indicates that the VAB / SPH is fully loaded and the GUI is ready).

Ah. That would account for the difference. I was triggering my log dump from a key press event handler so I was never trying to call it before all the VAB initialisation was complete.

23 hours ago, neitsa said:

It might also be a good option to refresh the list each time the player enters the VAB / SPH.

Depending on what you're using this for, it may also be a good idea to hook the onPartPurchased event.

Edited by Aelfhe1m
Link to comment
Share on other sites

19 minutes ago, Aelfhe1m said:

Ah. That would account for the difference. I was triggering my log dump from a key press event handler so I was never trying to call it before all the VAB initialisation was complete.

Ah exactly, that explains the differences in the output :)

20 minutes ago, Aelfhe1m said:

Depending on what you're using this for, it may also be a good idea to hook the onPartPurchased event

Neat idea! As of now I'm just trying to check if the vessel being built matches some part requirements (sort of a part check list before launch).

Thanks again for your feedback!

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