DMagic Posted June 29, 2014 Share Posted June 29, 2014 Is there anything I need to do to have a persistent scenario module?I tried making an empty one that just logs when it enters a function, but onload and onsave are never called.You need something to initialize it the first time. This will set which game scenes it will run in and store that in the persistent file. After that it should run onload and on save whenever you go to the relevant scene.Most of the Scenario Modules I've seen use basically the same method, so I would just check around. Quote Link to comment Share on other sites More sharing options...
Ippo Posted June 29, 2014 Share Posted June 29, 2014 You need something to initialize it the first time. This will set which game scenes it will run in and store that in the persistent file. After that it should run onload and on save whenever you go to the relevant scene.Most of the Scenario Modules I've seen use basically the same method, so I would just check around.Ok, so basically that's what Taranis is doing with this method, right? Quote Link to comment Share on other sites More sharing options...
DMagic Posted June 29, 2014 Share Posted June 29, 2014 Ok, so basically that's what Taranis is doing with this method, right?Yep. The if statement is the initial setup, the else statement is presumably used in case any extra game scenes need to be added in later versions. Quote Link to comment Share on other sites More sharing options...
Ippo Posted July 2, 2014 Share Posted July 2, 2014 Uh, maybe I'm doing something wrong here.I am shamelessly copying Taranis' code to inject my module into the game (hi!), but at the beginning of each scene, I get this popup:Also, in the persistent file, there is this: SCENARIO { name = TestScenarioModule scene = 5, 7, 6, 9 aSavedValue = modified and resumed from the persistent save }I should also note that I tried logging when my module executes OnLoad and OnSave, and got no signs of life from it. Here's the code in pastebin. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted July 2, 2014 Share Posted July 2, 2014 Uh, maybe I'm doing something wrong here.You're going to smack your head on the desk in about five seconds when I bold some stuff for youAlso, in the persistent file, there is this: SCENARIO { name = [SIZE=5][SIZE=3][B]TestScenarioModule[/B][/SIZE][/SIZE] scene = 5, 7, 6, 9 aSavedValue = modified and resumed from the persistent save }[snip]ProtoScenarioModule psm = game.scenarios.Find(s => s.moduleName == typeof([SIZE=5][B]TestScenarioModule[/B][/SIZE]).Name); if (psm == null) { Debug.Log("Adding the scenario module."); psm = game.AddProtoScenarioModule(typeof([B][SIZE=5]TestScenarioModule[/SIZE][/B]), GameScenes.SPACECENTER, GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPH);[...snip]public class [SIZE=3][B][SIZE=5]TestSM [/SIZE][/B][/SIZE]: ScenarioModuleSo you're actually adding a ScenarioModule called TestScenarioModule to the game. Unluckily for you, the game has one and it apparently writes a test value to the persistent file and opens a popup to display it. Your ScenarioModule, TestSM, never runs so of course you never see any output Quote Link to comment Share on other sites More sharing options...
Ippo Posted July 2, 2014 Share Posted July 2, 2014 ..."I'm too tired to study, let's code!" - clueless me 1 hour ago Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 3, 2014 Share Posted July 3, 2014 Because it has come up and I am doing exactly the same thing, here is the code that I am using to do this.Posting it so Ippo can see how I do it and for other people to comment if they see something wonky.This loads a scenario called OSJFlightusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Reflection;using UnityEngine;namespace OnScreenJoyStick{ [KSPAddon(KSPAddon.Startup.SpaceCentre, false)] //install our scenario module. is a partmodule so all calculations can be done in it, no need for a seperate plugin class in the scene class OSJMainMenu : MonoBehaviour { public void Start() { var game = HighLogic.CurrentGame; ProtoScenarioModule psm = game.scenarios.Find(s => s.moduleName == typeof(OSJFlight).Name); if (psm == null) { psm = game.AddProtoScenarioModule(typeof(OSJFlight), GameScenes.FLIGHT); } } } public class OSJFlight : ScenarioModule //this runs on flight scene start, no need for the KSPAddon as it is already loaded by the code in the SpaceCenter screen. {//All your plug in code here. Start, Update, FixedUpdate, OnSave, OnLoad, etc. all work as they do in a partmodule. } }The only thing about this is that I could not get the scenario to load if I used KSPAddon.Startup.MainMenu instead of .SpaceCenter.Not an issue for my current project as it runs in the flight scene only, but if what you are doing requires code to run on game start (such as a new career game with some sort of mission maybe?), that issue would have to be figured out.So, how close am I to how other people are doing this?D. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted July 3, 2014 Share Posted July 3, 2014 The only thing about this is that I could not get the scenario to load if I used KSPAddon.Startup.MainMenu instead of .SpaceCenter.Not an issue for my current project as it runs in the flight scene only, but if what you are doing requires code to run on game start (such as a new career game with some sort of mission maybe?), that issue would have to be figured out.That's because ScenarioModules are created on a per-persistent file basis. That's how the actual Scenarios ingame are made; they're just save games that somebody has manually added a savegame-specific ScenarioModule to. The main menu isn't associated with any particular game session so it wouldn't make sense for one to be loaded there.If you did need to run code before game start, I'd probably go with a separate, non-ScenarioModule KSPAddon that persisted between scenes. Once the player has loaded up a game, you could do whatever it is you wanted: store some info you collected during the main menu into your ScenarioModule, call a function or set up some parameters, etc. Then kill it and run your logic as normal Quote Link to comment Share on other sites More sharing options...
Timbo Posted July 3, 2014 Share Posted July 3, 2014 I'm trying to make a plug-in to automatically post screenshots to imgur. Is there an API I can use to take screenshots at will, or a way to hook into the F1 keypress event so I know a screenshot has been taken? Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 3, 2014 Share Posted July 3, 2014 (edited) I don't know about the API, but this will detect if the screenshot key is pressed. (Variables names not exact as this is from memory.)public void Update(){if(gameSettings.Screenshot.KeyCode != KeyCode.None & input.getkeydown(gameSettings.Screenshot.KeyCode)){print("ScreenShot!");}I'm pulling the screenshot key from the settings file here, that way if the player binds screenshot to another key, it will still be recognized.You also need to check that the keycode is not None as input.GetKeyDown returnes KeyCode.None if there is no key pressed that update. (I think, it may also return null, testing would be required.)D. Edited July 3, 2014 by Diazo Quote Link to comment Share on other sites More sharing options...
Timbo Posted July 3, 2014 Share Posted July 3, 2014 Thanks for the reply, that's along the lines of what I am looking for. But, how do I access the gameSettings object? Searching through the object browser, I see GameSettings is a class within Assembly-CSharp, however I don't see a "Screenshot" member within it. Furthermore, I can't seem to access anything Assembly-CSharp from within my code, although there is a reference to it in my project.I feel as though I am missing something key here, such as which classes should I be exploring to learn how to interact with the game? Is there a dev wiki that I haven't been able to find? I am using some sample code I found here http://forum.kerbalspaceprogram.com/threads/56053-Example-plugin-projects-to-help-you-get-started Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 3, 2014 Share Posted July 3, 2014 Alright, just to check you have the following set as dependencies correct?Assembly-CSharpUnityEngineAssembly-CSHarp-firstpass <- Optional, this is more for interacting with the GUI then the 3D game space.and then you added using UnityEngine; at the top of your project underneath all the other using statements that get added by default?D. Quote Link to comment Share on other sites More sharing options...
problemecium Posted July 3, 2014 Share Posted July 3, 2014 (edited) -removed, found answer myself- Edited July 3, 2014 by parameciumkid Quote Link to comment Share on other sites More sharing options...
Timbo Posted July 4, 2014 Share Posted July 4, 2014 Yes, but I can't seem to access anything within the Assembly-CSharp class. In fact, Intellisense does not show it as an option, and typing "Assembly-CSharp.gameSettings" generates an error in the IDE. Is this something to do with the hyphen in the class name? I am more of a VB guy and am relatively new to C# so perhaps I'm doing something stupid. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted July 4, 2014 Share Posted July 4, 2014 It's not a class. Here's a minimal example to get you started:using System;using UnityEngine;namespace TestPlugin{ [KSPAddon(KSPAddon.Startup.Flight, false)] public class ScreenshotTest : MonoBehaviour { void Update() { if (GameSettings.TAKE_SCREENSHOT.GetKeyDown()) Debug.Log("A screenshot was just taken!"); } }}If you have your references set up correctly, that will compile and you can start to tweak it as you like Quote Link to comment Share on other sites More sharing options...
Alex P Posted July 7, 2014 Share Posted July 7, 2014 Hi,I have this in a part module attached to an RCS block. It doesn't add any resources (I have tried Oxidizer also). I have also tried commenting out the if statement, and it still doesn't work. I've tried putting the code in OnFixedUpdate also. I got the part.RequestResource to work in another part module. What am I doing wrong here? Would OnFixedUpdate work better?private void OnDraw(){ if (CompressAir == true) { part.RequestResource("IntakeAir", -10); }}One more thing,[KSPEvent(guiActive = true, guiName = "Stop Compressing", active = true)]public void StopCompression(){ CompressAir = false;}I want to change "active = true" to "active = CompressAir" so the "Stop Compressing" button is only active when it is compressing. Instead, it gives me an error. How do I fix this? Quote Link to comment Share on other sites More sharing options...
Diazo Posted July 7, 2014 Share Posted July 7, 2014 On your first question about resources, I'm not sure as I have not dealt with them a lot. My only thought is do you have resource storage anywhere? Even just an placeholder with a storage size of 0?I remember reading something about that if there is no storage location present on the vessel, the resource does not generate as there is no place for KSP to put it. To get around this you have to add storage to your part, just with a maxSize of 0 so it does not store any resource.On the KSPEvent active question, I believe it is because the KSPEvent is pre-compiled and so the CompressAir variable does not exist. Instead, in your code where you change the state of CompressAir, add a KSPEvent.active = true (or false) as needed. (Syntax from memory and not correct.)Hope that helps.D. Quote Link to comment Share on other sites More sharing options...
Alex P Posted July 7, 2014 Share Posted July 7, 2014 It was attached to a half empty fuel tank, so I don't think that was the problem. I don't know much about KSPEvent, so I'll have to read up on that. Quote Link to comment Share on other sites More sharing options...
Ippo Posted July 7, 2014 Share Posted July 7, 2014 Actually it's because KSPEvent is an attribute, so when you declare it like that you can only use compile-time constants. You cannot use your variable directly, you will need to set the value each time:[COLOR=#333333]private void OnDraw(){[/COLOR][COLOR=#333333]if (CompressAir == true) {[/COLOR][COLOR=#333333]part.RequestResource("IntakeAir", -10);[/COLOR]this.Events["StopCompression"].active = true;[COLOR=#333333]}[/COLOR][COLOR=#333333]}[/COLOR][COLOR=#333333][KSPEvent(guiActive = true, guiName = "Stop Compressing", active = true)][/COLOR][COLOR=#333333]public void StopCompression(){[/COLOR][COLOR=#333333]CompressAir = false;[/COLOR]this.Events["StopCompression"].active = false;[COLOR=#333333]} Quote Link to comment Share on other sites More sharing options...
Ippo Posted July 8, 2014 Share Posted July 8, 2014 How can I run some code when a part collides?Specifically, I would like to run some calculations based on the impact velocity. I see that Part has three OnCollision* methods, but how can I get an event out of them in a PartModule? Quote Link to comment Share on other sites More sharing options...
blizzy78 Posted July 8, 2014 Share Posted July 8, 2014 How can I run some code when a part collides?I think GameEvents does have some collision hooks. Quote Link to comment Share on other sites More sharing options...
Timbo Posted July 9, 2014 Share Posted July 9, 2014 It's not a class. Here's a minimal example to get you started:using System;using UnityEngine;namespace TestPlugin{ [KSPAddon(KSPAddon.Startup.Flight, false)] public class ScreenshotTest : MonoBehaviour { void Update() { if (GameSettings.TAKE_SCREENSHOT.GetKeyDown()) Debug.Log("A screenshot was just taken!"); } }}If you have your references set up correctly, that will compile and you can start to tweak it as you likeThank you, that helped. Can you do me another favor and list the main classes I should explore to learn more about interacting with the game? Quote Link to comment Share on other sites More sharing options...
stupid_chris Posted July 10, 2014 Share Posted July 10, 2014 Thank you, that helped. Can you do me another favor and list the main classes I should explore to learn more about interacting with the game?Friendy reminder that decompiling is prohibited by the EULA and that this could put you into some serious trouble. However, you can use an assembly browser to look at the declarations of public members of the KSP classes without looking at the underlying code, which is permitted. And for what you need, it depends on what you want to do. FlightGlobals and HighLogic are useful classes, though most of what you will use will be Unity classes, and the docs for those are all around the internet. Quote Link to comment Share on other sites More sharing options...
Alex P Posted July 10, 2014 Share Posted July 10, 2014 Hi again,For some reason, this code doesn't seem to be working.public override void OnFixedUpdate(){ print ("This should say something..."); if (CompressAir == true) { print ("Should be compressing air..."); part.RequestResource("Oxidizer", -10); }}I think that should spam the log with at least one message every FixedUpdate. But, it doesn't, even when it's OnDraw. The KSPEvent buttons are able to print things to the log, but why can't I do this OnDraw or OnFixedUpdate?Thanks in advance. Quote Link to comment Share on other sites More sharing options...
Ippo Posted July 10, 2014 Share Posted July 10, 2014 Hi again,For some reason, this code doesn't seem to be working.public override void OnFixedUpdate(){ print ("This should say something..."); if (CompressAir == true) { print ("Should be compressing air..."); part.RequestResource("Oxidizer", -10); }}I think that should spam the log with at least one message every FixedUpdate. But, it doesn't, even when it's OnDraw. The KSPEvent buttons are able to print things to the log, but why can't I do this OnDraw or OnFixedUpdate?Thanks in advance.Use Debug.Log to write stuff to the log.Also, please use the tags when posting code. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.