Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

Hey guys. I'm starting mod development and I'd like to know if there are very simple mods I can download to start looking into the code. I've already downloaded some but they are too complex to start with (even Chatterer is already several k-lines of code). Thanks !

Link to comment
Share on other sites

[KSPAddon(KSPAddon.Startup.Flight, false)]
public class DrawGravity : MonoBehaviour
{
  	public bool inMapView;
	public void Start()
	{
      	GameEvents.OnMapEntered.Add(enteredMapView);
      	GameEvents.OnMapExited.Add(exitedMapView);
	}
  
	public void enteredMapView()
	{
	  	inMapView = true;
	}
  
	public void exitedMapView()
	{
      	inMapView = false;
	}
  	
	public void OnDestroy()
	{
      	GameEvents.OnMapEntered.Remove(enteredMapView);
      	GameEvents.OnMapExited.Remove(exitedMapView);
	}
  
	public void OnGUI()
	{
      	if (!inMapView)
        	return;
     	// stuff for drawing UI elements
      	// look up Unity's GUI or GUILayout classes
	}
}

Should be a fairly good starting point

Link to comment
Share on other sites

Hi, I've a very newbee question

I want to look at plugins devs, I used a lot VB.Net few years ago. I just went through a C# tutorial to freshen up my syntax. I'm installing VS 2015 (cummunity version).

My question is : As I want to create some "window" oriented plugin and not "part" oriented plugins, what version of Unity do I need to install ?

Thx

 

 

Link to comment
Share on other sites

None. Window oriented plugin you're looking at something very similar to what I posted 2 above your post. KSPAddon attribute on a monobehaviour, window drawn in OnGUI, lookup Unity GUI or GUILayout classes for documentation

NOTE: Unity's new GUI system isn't particularly plugin friendly, so you'll probably want the editor to play with that. However I'm under the impression that requires loading asset bundles which I don't believe are currently directly loadable by KSP

Edited by Crzyrndm
Link to comment
Share on other sites

3 hours ago, TheMaul said:

Hi, is there a way to debug plugins without restarting the game every time ?

Until 1.1 comes out which is supposed to support dynamic dll loading you could try this. But it has it's limitations.

Otherwise, restarting is the only way to do it.

Link to comment
Share on other sites

4 hours ago, sarbian said:

AssemblyReloader supports this btw in case it wasn't clear, so you can reload and debug your iterations. Most of its limitations are because I haven't needed that functionality and nobody's asked for it

Link to comment
Share on other sites

10 hours ago, xEvilReeperx said:

AssemblyReloader supports this btw in case it wasn't clear, so you can reload and debug your iterations. Most of its limitations are because I haven't needed that functionality and nobody's asked for it

Oh, I ll have to look into it more then :)

Link to comment
Share on other sites

10 hours ago, xEvilReeperx said:

AssemblyReloader supports this btw in case it wasn't clear, so you can reload and debug your iterations. Most of its limitations are because I haven't needed that functionality and nobody's asked for it

Sorry dude, I just meant it doesn't cover everything. My mods all have parts, contracts or internal models, so it's not much use to me personally.

Link to comment
Share on other sites

  • 2 weeks later...

I wrote my own code to detect which asteroid are heading for kerbin and when. That bit is working great and It auto-add the SOI change to KAC. The part that is not working is making custom contracts based on that information.

Because the orbits are only available during the FLIGHT and TRACKSTATION GameScenes, I have my code try to generate a custom contract and add it to the current ones. Problem is, it doesn't seems to do anything. The contracts doesn't show up, even in the debug menu. Here is the code:

 

private void AddContract(String vID)
		{
			//Add Contract if possible


			Debug.Log ("Try to find Contract for " + vID);

			Debug.Log ("number of Contracts to check : " + ContractSystem.Instance.Contracts.Count ());
			Debug.Log ("Status of Contract system: " + (ContractSystem.Instance == null));
			Debug.Log ("ContractSystem.Instance.enabled: " + ContractSystem.Instance.enabled);

			Debug.Log ("Generating new Contract ");
			AsteroidRedirectContract GeneratedContractType = new AsteroidRedirectContract ();
			Contract GeneratedContract = null;
			Debug.Log ("Generating Contract of Type:" + GeneratedContractType.GetType ());

			GeneratedContract = ContractSystem.Instance.GenerateContract (0, Contract.ContractPrestige.Trivial, GeneratedContractType.GetType ());
			if (GeneratedContract != null) {
				GeneratedContract.AddParameter (new AsteroidRedirectAltitudeParameters (vID));
				GeneratedContract.AddParameter (new AsteroidRedirectDockingParameters (vID));
			}
				
			if (!ContractSystem.Instance.Contracts.Contains(GeneratedContract)) 
			{
				//Generate new Contract
			
				GeneratedContract.Accept ();

				ContractSystem.Instance.Contracts.Add (GeneratedContract);
				Debug.Log ("Generated Contract:" + GeneratedContract.ToString ());
			}

		}

Now, I am obvious not a C# or Unity developper, so I have no clue if I'm doing something that is obviously wrong.... I've tried to debug this for hours trying various way and none seems to work, which is why I am posting here... 

ContractSystem.Instance.Contracts.Count (), keeps going up with every contract that I Add(). So that seems to be working. Except, it doesn't do anything.

Any Ideas?

Link to comment
Share on other sites

Hi all,

I really really really really really really (yes, really :-P) Hope someone can see where I'm going wrong on this......

What I'm trying to do is spawn a vessel (loaded from an existing Craft file) at startup, using KSPAddon to trigger the spawning when you enter the space center from the main menu, when I've got it working there will be a check to see if the vessel already exists, but for now I just want to get it to spawn.

I've got it triggering the code, but then something weird is happening and it's driving me nuts.

Any time after a certain point that I try to do anything with the _newVessel I get an exception and it breaks.

The Exception (from the log) is 

Quote

[EXC 20:13:37.146] NullReferenceException: Object reference not set to an instance of an object
    Kerbal_Stargate.VesselSpawner.SpawnVessel (System.String vesselName, .ShipConstruct _shipConstruct, Vector3 _spawnOffset)
    Kerbal_Stargate.VesselSpawner.SpawnVessel ()
    Kerbal_Stargate.TMS_Module_001.Awake ()
    UnityEngine.GameObject:AddComponent(Type)
    AddonLoader:StartAddon(LoadedAssembly, Type, KSPAddon, Startup)
    AddonLoader:StartAddons(Startup)
    AddonLoader:OnLevelWasLoaded(Int32)

 

The code (below) is a modified version of KSPSmelter by @TAz00, which in turn is a modified bit of code from KAS.

The biggest problem has been converting the code to spawn at a specific point in the 'universe' from spawning based on the position of a Part, so I think I've broken something somewhere.  The actual spawn location isn't important at the moment, I'll be translating save game position data to place the object once I have this part working properly.

I've been staring/fiddling/kicking this code for almost two days solid so I really do hope someone can help out. :)

 

Code for creating/spawning the vessel.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace TMS_Module_001
{
    /// <summary>
    /// This class is pretty much built on what KAS uses to pull parts out of containers
    /// All credit to https://github.com/KospY/KAS
    /// https://github.com/KospY/KAS/blob/master/LICENSE.md
    /// </summary>
    public class VesselSpawner
    {
        const string PluginPath = "\\GameData\\TMSOrbitalMechanics\\PluginData\\";

        private HideConfigNode _OldVabShip;
        private string _craftFile = "";
        private string vesselName = "";
        private Vector3 vesselPosition = new Vector3(0.0f, 0.0f, 0.0f);
        private CelestialBody bodyKerbin = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_craftFile">Craft file name as it appears in the PluginPath folder</param>
        /// <param name="_srcPart">Source part to spawn relative to</param>
        /// <param name="_spawnOffset">Offset spawn from Source part position</param>
        //public VesselSpawner(string _craftFile, Vector3 _spawnOffset)
        public VesselSpawner(string _craftFile, string vesselName, Vector3 vesselPosition, CelestialBody bodyKerbin)
        {
            //Store paths
            this._craftFile = _craftFile;
            this.vesselPosition = vesselPosition;
            this.vesselName = vesselName;
            this.bodyKerbin = bodyKerbin;

        }

        /// <summary>
        /// Spawns the vessel
        /// </summary>
        public void SpawnVessel()
        {
            Debug.Log("SpawnVessel");
            //Load craft file
            ShipConstruct _ship = LoadVessel(this._craftFile);
            if (_ship != null)
            {
                SpawnVessel(this.vesselName, _ship, this.vesselPosition);
            }
            else
            {
                Debug.Log("Failed to load the vessel");
            }
        }

        /// <summary>
        /// Attempt vessel load
        /// </summary>
        /// <param name="_craftFile"></param>
        /// <returns></returns>
        private ShipConstruct LoadVessel(string _craftFile)
        {
            Debug.Log("ConstructVessel");
            //Get path to vessel
            Debug.Log("Loading the craft file");
            string BasePath = Environment.CurrentDirectory + PluginPath;
            string path = BasePath + _craftFile;
            Debug.Log(path);
            //Save old ship for later, else player will see it in the VAB
            _OldVabShip = new HideConfigNode(ShipConstruction.ShipConfig);

            //Load craft file
            ShipConstruct _shipConstruct = ShipConstruction.LoadShip(path);

            //Check load
            Debug.Log("Checking if its loaded");
            if (_shipConstruct == null)
            {
                // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB
                ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode();
                return null; //Fail
            }
            Debug.Log("Sending it back");
            return _shipConstruct;
        }

        /// <summary>
        /// Spawn ship construct
        /// https://github.com/KospY/KAS/blob/master/Plugin/KAS_Shared.cs
        /// </summary>
        /// <param name="_shipConstruct">Shipconstruct to spawn</param>
        /// <param name="_srcPart">Source part to spawn relative to</param>
        /// <param name="_spawnOffset">Offset spawn from Source part position</param>
        private void SpawnVessel(string vesselName, ShipConstruct _shipConstruct, Vector3 _spawnOffset)
        {
            Debug.Log("PrivateSpawnVessel");
            //Store construct root
            Part _newConstructRootPart = _shipConstruct.parts[0];

            Debug.Log("Doing something with the Root");
            //Center rootpart
            Vector3 offset = _newConstructRootPart.transform.localPosition;
            _newConstructRootPart.transform.Translate(-offset);

            Debug.Log("Setting Root position or something");
            //Get launch spawn point.
            
            GameObject launchPos = new GameObject();
            launchPos.transform.position = vesselPosition;

            //Store our launch / spawn position
            Transform launchTransform = launchPos.transform;

            //Kill original object
            launchPos.DestroyGameObject();

            //Set rootpart origin
            _shipConstruct.Parts[0].localRoot.transform.Translate(launchPos.transform.position, Space.World);

            //Position
            float angle;
            Vector3 axis;

            //Extract ToAngleAxis data from selected spawning location
            launchTransform.rotation.ToAngleAxis(out angle, out axis);

            //TRANSFORM Rotate localRootPart in relation to root
            _shipConstruct.Parts[0].localRoot.transform.RotateAround(launchTransform.position, axis, angle);

            //Create vessel object
            Debug.Log("CreateVesselObject");
            Vessel _newVessel = _newConstructRootPart.localRoot.gameObject.AddComponent<Vessel>();

            Debug.Log("Adding all the info to the ship");
            //Attach vessel information
            _newVessel.id = Guid.NewGuid();
            _newVessel.name = vesselName;
            //_newVessel.Landed = true;
            _newVessel.Splashed = false;
            _newVessel.landedAt = string.Empty;
            _newVessel.situation = Vessel.Situations.LANDED;
            _newVessel.vesselType = VesselType.Base;

            //Init from VAB
            _newVessel.Initialize(true);

            //_newVessel.vesselName = _srcPart.vessel.vesselName + " - " + _shipConstruct.shipName;
            //_newVessel.landedAt = _srcPart.vessel.vesselName;

            //Store backup
            ShipConstruction.CreateBackup(_shipConstruct);

            Debug.Log("MissionIDStuff");
            
            //Set Orbit
            InitiateOrbit(vesselPosition, _newVessel);

            //Set Mission info
            Debug.Log("Set Mission ID");
            uint missionId = (uint)Guid.NewGuid().GetHashCode();
            //string flagUrl = _srcPart.flagURL;
            Debug.Log("Set Launch ID");
            uint launchId = HighLogic.CurrentGame.launchID++;

            //Set part mission info
            for (int i = 0; i < _newVessel.parts.Count; i++) 
            {
                Debug.Log(_newVessel.parts.Count);
                Debug.Log("Loop through parts");
                Part part = _newVessel.parts[i];
                Debug.Log(part.name);
                part.flightID = ShipConstruction.GetUniqueFlightID(FlightDriver.FlightStateCache.flightState);
                Debug.Log("Done it Once");
                part.launchID = launchId;
                part.missionID = missionId;
            }
            Debug.Log("Finished Mission Stuff");
            //Generate staging
            //Staging.beginFlight();
            //_newConstructRootPart.vessel.ResumeStaging();
            //Staging.GenerateStagingSequence(_newConstructRootPart.localRoot);
            //Staging.RecalculateVesselStaging(_newConstructRootPart.vessel);

            //Set position, again
            _newVessel.SetPosition(launchTransform.position);
            _newVessel.SetRotation(launchTransform.rotation);

            //Get all the parts, does it even matter since we launch from VAB?
            for (int i = 0; i < _newVessel.parts.Count; i++)
            {
                // Solar panels from containers (we dont have no bloody containers here tho) don't work otherwise
                for (int j = 0; j < _newVessel.parts[i].Modules.Count; j++)
                {
                    ConfigNode node = new ConfigNode();
                    node.AddValue("name", _newVessel.parts[i].Modules[j].moduleName);
                    _newVessel.parts[i].LoadModule(node, ref j);
                }
            }

            Debug.Log("ProtoVesselStuff");
            //Save Protovessel
            ProtoVessel _newProto = new ProtoVessel(_newVessel);

            Debug.Log("Defined ProtoVessel");

            if (_newProto == null)
            {
                Debug.Log("Nope");
            }
                
            else
            {
                Debug.Log("If Statement if not failed");

                //Kill and remove spawned vessel, had some serious problems with spawn position warping/glitching
                //
                Debug.Log("_newVessel Die");
                _newVessel.Die();
                Debug.Log("New Vessel Dead");


                Debug.Log(launchPos.transform.position);
                //Set the protovessels position to the relative one we found, maybe redundant
                Debug.Log("Move ProtoVessel");
                _newProto.position = launchPos.transform.position;
                

                //If you check this value, you will see the height change from launch scene to resume scene, extra dafuq
                
                float height = _newProto.height;

                if (FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_FILE ||
                    FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_CACHE)
                {
                    //Odd behaviour with positioning during different flight scenes, workaround awaaaay
                    //_newProto.height = TrueAlt(launchTransform.position, _newProto.height);
                //}

                //Load Protovessel
                Debug.Log("ProtoVessel Load");
                _newProto.Load(HighLogic.CurrentGame.flightState);

                // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB
                ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode();
                }
            }
        }

        /// <summary>
        /// http://forum.kerbalspaceprogram.com/threads/111116-KSP-Altitude-Calculation-Inquiry
        /// </summary>
        /// <returns></returns>
        //private float TrueAlt(Vector3 _LauncPos, Vessel _srcVessel)
        //{
        //    Debug.Log("Altitude Stuff?");
        //    //Vector3 pos = _srcPart.transform.position; //or this.vessel.GetWorldPos3D()
        //   float ASL = FlightGlobals.getAltitudeAtPos(_LauncPos);
        //    if (_srcVessel.mainBody.pqsController == null) { return ASL; }
        //    float terrainAlt = Convert.ToSingle(_srcVessel.pqsAltitude);
        //    if (_srcVessel.mainBody.ocean && _srcVessel.heightFromTerrain <= 0) { return ASL; } //Checks for oceans
        //    return ASL - terrainAlt;
        //}

        /// <summary>
        /// https://github.com/taniwha-qf/Extraplanetary-Launchpads/blob/master/Source/BuildControl.cs
        /// https://github.com/taniwha-qf/Extraplanetary-Launchpads/blob/master/License.txt
        /// </summary>
        /// <param name="_newVessel"></param>
        /// <param name="_srcVessel"></param>
        private void InitiateOrbit(Vector3 vesselPosition, Vessel _newVessel)
        {
           Debug.Log("More OrbitStuff");
           var mode = OrbitDriver.UpdateMode.UPDATE;
           _newVessel.orbitDriver.SetOrbitMode(mode);
        
           var craftCoM = GetVesselWorldCoM(_newVessel);
           //var vesselCoM = _newVessel.findWorldCenterOfMass;

           var uTime = Planetarium.GetUniversalTime();

           var vesselCoM = vesselPosition;
           var offset = (Vector3d.zero + craftCoM - vesselCoM).xzy;

           _newVessel.orbit.Init();
           _newVessel.orbit.StartUT = uTime;
           _newVessel.orbit.referenceBody = bodyKerbin;
           //_newVessel.orbit.pos = vesselPosition;
           //_newVessel.orbit.vel = new Vector3d(0, 0, 0);
           //_newVessel.angularMomentum = Vector3.zero;
           //_newVessel.angularVelocity = Vector3.zero;
           _newVessel.latitude = -1.0f;
           _newVessel.longitude = 1.0f;
           _newVessel.heightFromTerrain = 0.0f;
           //_newVessel.SetRotation(0,0);
           //_newVessel.altitude = 70.8178020151099;

           var corb = _newVessel.orbit;

           corb.UpdateFromStateVectors(corb.pos + offset, _newVessel.orbit.vel, bodyKerbin, uTime);

           Debug.Log(String.Format("[EL] {0} {1}", "This is Orbit Info", corb.pos));

        }

        public Vector3 GetVesselWorldCoM(Vessel v)
        {
           var com = v.findLocalCenterOfMass();
            return v.rootPart.partTransform.TransformPoint(com);
        }
    }
}

The trouble starts when I hit the line.....

part.flightID = ShipConstruction.GetUniqueFlightID(FlightDriver.FlightStateCache.flightState);

Just as an excersize I commented out that line, and then it threw the exception at

Debug.Log("_newVessel Die");
      _newVessel.Die();
Debug.Log("New Vessel Dead");

leading me to think that it's something to do with the way I've created/modified the vessel. :-/

Code for calling the spawn......

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace TMS_Module_001
{
    [KSPAddon(KSPAddon.Startup.SpaceCentre, true)]

    public class TMS_Stargate : MonoBehaviour
    {
        public CelestialBody bodyMun;
        public CelestialBody bodyKerbin;

        public void Awake()
        {

            string vesselName = "Module 001";
            
            //string celestialBody = "Kerbin";
            //CelestialBody celestialBody = new CelestialBody();

            foreach (CelestialBody targetBody in FlightGlobals.Bodies)
            {           
                if (targetBody.name == "Kerbin")
                bodyKerbin = targetBody;
            }

            //string targetBody = celestialBody.name;
            Vector3 vesselPosition = new Vector3(5f, 0f, 5f);

            VesselSpawner TMS_Module_001 = new VesselSpawner("TMS_Module_001.craft", vesselName, vesselPosition, bodyKerbin);

            Debug.Log("Spawn the Ship");
            TMS_Module_001.SpawnVessel();
            Debug.Log("Ship has Spawned");
        }

    }
}

 

So again, I really hope someone can shed some light on this, even if it's a case of pointing me in the right direction of what to look at :)

Thanks

TheMightySpud

Link to comment
Share on other sites

11 hours ago, TheMightySpud said:

Hi all,

I really really really really really really (yes, really :-P) Hope someone can see where I'm going wrong on this......

What I'm trying to do is spawn a vessel (loaded from an existing Craft file) at startup, using KSPAddon to trigger the spawning when you enter the space center from the main menu, when I've got it working there will be a check to see if the vessel already exists, but for now I just want to get it to spawn.

I've got it triggering the code, but then something weird is happening and it's driving me nuts.

Any time after a certain point that I try to do anything with the _newVessel I get an exception and it breaks.

The Exception (from the log) is 

 

The code (below) is a modified version of KSPSmelter by @TAz00, which in turn is a modified bit of code from KAS.

The biggest problem has been converting the code to spawn at a specific point in the 'universe' from spawning based on the position of a Part, so I think I've broken something somewhere.  The actual spawn location isn't important at the moment, I'll be translating save game position data to place the object once I have this part working properly.

I've been staring/fiddling/kicking this code for almost two days solid so I really do hope someone can help out. :)

 

Code for creating/spawning the vessel.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace TMS_Module_001
{
    /// <summary>
    /// This class is pretty much built on what KAS uses to pull parts out of containers
    /// All credit to https://github.com/KospY/KAS
    /// https://github.com/KospY/KAS/blob/master/LICENSE.md
    /// </summary>
    public class VesselSpawner
    {
        const string PluginPath = "\\GameData\\TMSOrbitalMechanics\\PluginData\\";

        private HideConfigNode _OldVabShip;
        private string _craftFile = "";
        private string vesselName = "";
        private Vector3 vesselPosition = new Vector3(0.0f, 0.0f, 0.0f);
        private CelestialBody bodyKerbin = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_craftFile">Craft file name as it appears in the PluginPath folder</param>
        /// <param name="_srcPart">Source part to spawn relative to</param>
        /// <param name="_spawnOffset">Offset spawn from Source part position</param>
        //public VesselSpawner(string _craftFile, Vector3 _spawnOffset)
        public VesselSpawner(string _craftFile, string vesselName, Vector3 vesselPosition, CelestialBody bodyKerbin)
        {
            //Store paths
            this._craftFile = _craftFile;
            this.vesselPosition = vesselPosition;
            this.vesselName = vesselName;
            this.bodyKerbin = bodyKerbin;

        }

        /// <summary>
        /// Spawns the vessel
        /// </summary>
        public void SpawnVessel()
        {
            Debug.Log("SpawnVessel");
            //Load craft file
            ShipConstruct _ship = LoadVessel(this._craftFile);
            if (_ship != null)
            {
                SpawnVessel(this.vesselName, _ship, this.vesselPosition);
            }
            else
            {
                Debug.Log("Failed to load the vessel");
            }
        }

        /// <summary>
        /// Attempt vessel load
        /// </summary>
        /// <param name="_craftFile"></param>
        /// <returns></returns>
        private ShipConstruct LoadVessel(string _craftFile)
        {
            Debug.Log("ConstructVessel");
            //Get path to vessel
            Debug.Log("Loading the craft file");
            string BasePath = Environment.CurrentDirectory + PluginPath;
            string path = BasePath + _craftFile;
            Debug.Log(path);
            //Save old ship for later, else player will see it in the VAB
            _OldVabShip = new HideConfigNode(ShipConstruction.ShipConfig);

            //Load craft file
            ShipConstruct _shipConstruct = ShipConstruction.LoadShip(path);

            //Check load
            Debug.Log("Checking if its loaded");
            if (_shipConstruct == null)
            {
                // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB
                ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode();
                return null; //Fail
            }
            Debug.Log("Sending it back");
            return _shipConstruct;
        }

        /// <summary>
        /// Spawn ship construct
        /// https://github.com/KospY/KAS/blob/master/Plugin/KAS_Shared.cs
        /// </summary>
        /// <param name="_shipConstruct">Shipconstruct to spawn</param>
        /// <param name="_srcPart">Source part to spawn relative to</param>
        /// <param name="_spawnOffset">Offset spawn from Source part position</param>
        private void SpawnVessel(string vesselName, ShipConstruct _shipConstruct, Vector3 _spawnOffset)
        {
            Debug.Log("PrivateSpawnVessel");
            //Store construct root
            Part _newConstructRootPart = _shipConstruct.parts[0];

            Debug.Log("Doing something with the Root");
            //Center rootpart
            Vector3 offset = _newConstructRootPart.transform.localPosition;
            _newConstructRootPart.transform.Translate(-offset);

            Debug.Log("Setting Root position or something");
            //Get launch spawn point.
            
            GameObject launchPos = new GameObject();
            launchPos.transform.position = vesselPosition;

            //Store our launch / spawn position
            Transform launchTransform = launchPos.transform;

            //Kill original object
            launchPos.DestroyGameObject();

            //Set rootpart origin
            _shipConstruct.Parts[0].localRoot.transform.Translate(launchPos.transform.position, Space.World);

            //Position
            float angle;
            Vector3 axis;

            //Extract ToAngleAxis data from selected spawning location
            launchTransform.rotation.ToAngleAxis(out angle, out axis);

            //TRANSFORM Rotate localRootPart in relation to root
            _shipConstruct.Parts[0].localRoot.transform.RotateAround(launchTransform.position, axis, angle);

            //Create vessel object
            Debug.Log("CreateVesselObject");
            Vessel _newVessel = _newConstructRootPart.localRoot.gameObject.AddComponent<Vessel>();

            Debug.Log("Adding all the info to the ship");
            //Attach vessel information
            _newVessel.id = Guid.NewGuid();
            _newVessel.name = vesselName;
            //_newVessel.Landed = true;
            _newVessel.Splashed = false;
            _newVessel.landedAt = string.Empty;
            _newVessel.situation = Vessel.Situations.LANDED;
            _newVessel.vesselType = VesselType.Base;

            //Init from VAB
            _newVessel.Initialize(true);

            //_newVessel.vesselName = _srcPart.vessel.vesselName + " - " + _shipConstruct.shipName;
            //_newVessel.landedAt = _srcPart.vessel.vesselName;

            //Store backup
            ShipConstruction.CreateBackup(_shipConstruct);

            Debug.Log("MissionIDStuff");
            
            //Set Orbit
            InitiateOrbit(vesselPosition, _newVessel);

            //Set Mission info
            Debug.Log("Set Mission ID");
            uint missionId = (uint)Guid.NewGuid().GetHashCode();
            //string flagUrl = _srcPart.flagURL;
            Debug.Log("Set Launch ID");
            uint launchId = HighLogic.CurrentGame.launchID++;

            //Set part mission info
            for (int i = 0; i < _newVessel.parts.Count; i++) 
            {
                Debug.Log(_newVessel.parts.Count);
                Debug.Log("Loop through parts");
                Part part = _newVessel.parts[i];
                Debug.Log(part.name);
                part.flightID = ShipConstruction.GetUniqueFlightID(FlightDriver.FlightStateCache.flightState);
                Debug.Log("Done it Once");
                part.launchID = launchId;
                part.missionID = missionId;
            }
            Debug.Log("Finished Mission Stuff");
            //Generate staging
            //Staging.beginFlight();
            //_newConstructRootPart.vessel.ResumeStaging();
            //Staging.GenerateStagingSequence(_newConstructRootPart.localRoot);
            //Staging.RecalculateVesselStaging(_newConstructRootPart.vessel);

            //Set position, again
            _newVessel.SetPosition(launchTransform.position);
            _newVessel.SetRotation(launchTransform.rotation);

            //Get all the parts, does it even matter since we launch from VAB?
            for (int i = 0; i < _newVessel.parts.Count; i++)
            {
                // Solar panels from containers (we dont have no bloody containers here tho) don't work otherwise
                for (int j = 0; j < _newVessel.parts[i].Modules.Count; j++)
                {
                    ConfigNode node = new ConfigNode();
                    node.AddValue("name", _newVessel.parts[i].Modules[j].moduleName);
                    _newVessel.parts[i].LoadModule(node, ref j);
                }
            }

            Debug.Log("ProtoVesselStuff");
            //Save Protovessel
            ProtoVessel _newProto = new ProtoVessel(_newVessel);

            Debug.Log("Defined ProtoVessel");

            if (_newProto == null)
            {
                Debug.Log("Nope");
            }
                
            else
            {
                Debug.Log("If Statement if not failed");

                //Kill and remove spawned vessel, had some serious problems with spawn position warping/glitching
                //
                Debug.Log("_newVessel Die");
                _newVessel.Die();
                Debug.Log("New Vessel Dead");


                Debug.Log(launchPos.transform.position);
                //Set the protovessels position to the relative one we found, maybe redundant
                Debug.Log("Move ProtoVessel");
                _newProto.position = launchPos.transform.position;
                

                //If you check this value, you will see the height change from launch scene to resume scene, extra dafuq
                
                float height = _newProto.height;

                if (FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_FILE ||
                    FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_CACHE)
                {
                    //Odd behaviour with positioning during different flight scenes, workaround awaaaay
                    //_newProto.height = TrueAlt(launchTransform.position, _newProto.height);
                //}

                //Load Protovessel
                Debug.Log("ProtoVessel Load");
                _newProto.Load(HighLogic.CurrentGame.flightState);

                // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB
                ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode();
                }
            }
        }

        /// <summary>
        /// http://forum.kerbalspaceprogram.com/threads/111116-KSP-Altitude-Calculation-Inquiry
        /// </summary>
        /// <returns></returns>
        //private float TrueAlt(Vector3 _LauncPos, Vessel _srcVessel)
        //{
        //    Debug.Log("Altitude Stuff?");
        //    //Vector3 pos = _srcPart.transform.position; //or this.vessel.GetWorldPos3D()
        //   float ASL = FlightGlobals.getAltitudeAtPos(_LauncPos);
        //    if (_srcVessel.mainBody.pqsController == null) { return ASL; }
        //    float terrainAlt = Convert.ToSingle(_srcVessel.pqsAltitude);
        //    if (_srcVessel.mainBody.ocean && _srcVessel.heightFromTerrain <= 0) { return ASL; } //Checks for oceans
        //    return ASL - terrainAlt;
        //}

        /// <summary>
        /// https://github.com/taniwha-qf/Extraplanetary-Launchpads/blob/master/Source/BuildControl.cs
        /// https://github.com/taniwha-qf/Extraplanetary-Launchpads/blob/master/License.txt
        /// </summary>
        /// <param name="_newVessel"></param>
        /// <param name="_srcVessel"></param>
        private void InitiateOrbit(Vector3 vesselPosition, Vessel _newVessel)
        {
           Debug.Log("More OrbitStuff");
           var mode = OrbitDriver.UpdateMode.UPDATE;
           _newVessel.orbitDriver.SetOrbitMode(mode);
        
           var craftCoM = GetVesselWorldCoM(_newVessel);
           //var vesselCoM = _newVessel.findWorldCenterOfMass;

           var uTime = Planetarium.GetUniversalTime();

           var vesselCoM = vesselPosition;
           var offset = (Vector3d.zero + craftCoM - vesselCoM).xzy;

           _newVessel.orbit.Init();
           _newVessel.orbit.StartUT = uTime;
           _newVessel.orbit.referenceBody = bodyKerbin;
           //_newVessel.orbit.pos = vesselPosition;
           //_newVessel.orbit.vel = new Vector3d(0, 0, 0);
           //_newVessel.angularMomentum = Vector3.zero;
           //_newVessel.angularVelocity = Vector3.zero;
           _newVessel.latitude = -1.0f;
           _newVessel.longitude = 1.0f;
           _newVessel.heightFromTerrain = 0.0f;
           //_newVessel.SetRotation(0,0);
           //_newVessel.altitude = 70.8178020151099;

           var corb = _newVessel.orbit;

           corb.UpdateFromStateVectors(corb.pos + offset, _newVessel.orbit.vel, bodyKerbin, uTime);

           Debug.Log(String.Format("[EL] {0} {1}", "This is Orbit Info", corb.pos));

        }

        public Vector3 GetVesselWorldCoM(Vessel v)
        {
           var com = v.findLocalCenterOfMass();
            return v.rootPart.partTransform.TransformPoint(com);
        }
    }
}

The trouble starts when I hit the line.....


part.flightID = ShipConstruction.GetUniqueFlightID(FlightDriver.FlightStateCache.flightState);

Just as an excersize I commented out that line, and then it threw the exception at


Debug.Log("_newVessel Die");
      _newVessel.Die();
Debug.Log("New Vessel Dead");

leading me to think that it's something to do with the way I've created/modified the vessel. :-/

Code for calling the spawn......


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace TMS_Module_001
{
    [KSPAddon(KSPAddon.Startup.SpaceCentre, true)]

    public class TMS_Stargate : MonoBehaviour
    {
        public CelestialBody bodyMun;
        public CelestialBody bodyKerbin;

        public void Awake()
        {

            string vesselName = "Module 001";
            
            //string celestialBody = "Kerbin";
            //CelestialBody celestialBody = new CelestialBody();

            foreach (CelestialBody targetBody in FlightGlobals.Bodies)
            {           
                if (targetBody.name == "Kerbin")
                bodyKerbin = targetBody;
            }

            //string targetBody = celestialBody.name;
            Vector3 vesselPosition = new Vector3(5f, 0f, 5f);

            VesselSpawner TMS_Module_001 = new VesselSpawner("TMS_Module_001.craft", vesselName, vesselPosition, bodyKerbin);

            Debug.Log("Spawn the Ship");
            TMS_Module_001.SpawnVessel();
            Debug.Log("Ship has Spawned");
        }

    }
}

 

So again, I really hope someone can shed some light on this, even if it's a case of pointing me in the right direction of what to look at :)

Thanks

TheMightySpud

The most obvious thing to check is that bodyKerbin in not null; it's not guaranteed to be set by your loop through FlightGlobal.Bodies.  You should check right after the loop if it is null.

I'm not sure if FlightGlobals will work in the main menu; it might work only in flight.

For debugging, a thing I often do is check if each variable I'm about to pass is null (vesselName, vesselPosition, bodyKerbin) and print a message and return if it is, and print the value if it's not null (so I know I'm passing the right values).

Then disable the printing for the release version.  You can wrap the debugging in #if DEBUG / #endif so that it only is compiled for the debug version

6 hours ago, ShadyAct said:

Will a 32-bit plugin run any differently on 64-bit KSP if it's compiled with x64 assemblies? (UnityEngine, etc.)

My gut says it should work, but it's not a great idea.

I keep a totally separate copy of KSP for development, with the sound off and all the graphics set to "terrible but fast", and only the mods needed for testing (if any).  It makes loading a whole lot faster than trying to load my "real" copy of the copy.

(You don't need to buy the game again, just copy the directory)

Link to comment
Share on other sites

7 hours ago, ShadyAct said:

Will a 32-bit plugin run any differently on 64-bit KSP if it's compiled with x64 assemblies? (UnityEngine, etc.)

KSP plugin works fine on both unless they use native code (most don't) or where specifically build to use an architecture (which is not the default)

Link to comment
Share on other sites

18 hours ago, ShadyAct said:

Could you give me an example of native code?

Most of Principia is written in native code (C++) except for a little C# for integrating it into KSP. That's the only one I know. It happens rarely because it is more hassle than it's worth unless you need the speed improvements afforded by having some native code.

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