Пример #1
0
        /// <summary>
        /// Verifies that the ReesearchBodies version the player has is compatible.
        /// </summary>
        /// <returns>Whether the check passed.</returns>
        public static bool VerifyResearchBodiesVersion()
        {
            string minVersion = "1.8";

            if (ResearchBodiesAssembly == null && !ResearchBodiesCheckDone)
            {
                ResearchBodiesAssembly  = Version.VerifyAssemblyVersion("ResearchBodies", minVersion, true);
                ResearchBodiesCheckDone = true;
            }

            // Check the wrapper is initalized, while we're here
            if (ResearchBodiesAssembly != null && !RBWrapper.APIRBReady)
            {
                // Initialize the Research Bodies wrapper
                bool rbInit = RBWrapper.InitRBWrapper();
                if (rbInit)
                {
                    LoggingUtil.LogInfo(typeof(ContractConfigurator), "Successfully initialized Research Bodies wrapper.");
                }
                else
                {
                    LoggingUtil.LogDebug(typeof(ContractConfigurator), "Couldn't initialize Research Bodies wrapper.");
                }
            }

            return(ResearchBodiesAssembly != null);
        }
Пример #2
0
        public void Update()
        {
            // Delay until the game database has started loading (it's a short delay)
            if (LoadingScreen.Instance != null && GameDatabase.Instance != null && GameDatabase.Instance.root != null)
            {
                LoggingUtil.LogDebug(this, "Adding custom loading tips");

                // Add the Contract Configurator tip
                List <string> contractTips = new List <string>();
                contractTips.Add("Configuring Contracts...");

                // Read tips from root contract groups
                ConfigNode[] contractGroups = GameDatabase.Instance.GetConfigNodes("CONTRACT_GROUP");
                foreach (ConfigNode groupConfig in contractGroups)
                {
                    if (groupConfig.HasValue("tip"))
                    {
                        foreach (string tip in groupConfig.GetValues("tip"))
                        {
                            contractTips.Add(tip);
                        }
                    }
                }

                foreach (LoadingScreen.LoadingScreenState lss in LoadingScreen.Instance.Screens)
                {
                    // Append our custom tips
                    lss.tips = lss.tips.Union(contractTips).ToArray();
                }

                Destroy(this);
            }
        }
Пример #3
0
        protected override void TriggerAction()
        {
            string[]      srcPathComponents = new string[] { KSPUtil.ApplicationRootPath, "GameData" }.Concat(url.Split("/".ToCharArray())).ToArray();
            List <string> destPathComponents = new string[] { KSPUtil.ApplicationRootPath, "saves", HighLogic.SaveFolder }.ToList();

            if (craftType == CraftType.SubAssembly)
            {
                destPathComponents.Add("Subassemblies");
            }
            else
            {
                destPathComponents.Add("Ships");
                destPathComponents.Add(craftType.ToString());
            }
            destPathComponents.Add(srcPathComponents.Last());

            string srcPath = string.Join(Path.DirectorySeparatorChar.ToString(), srcPathComponents);
            string destPath = string.Join(Path.DirectorySeparatorChar.ToString(), destPathComponents.ToArray());

            LoggingUtil.LogDebug(this, "Copying from '{0}' to '{1}'.", srcPath, destPath);
            try
            {
                File.Copy(srcPath, destPath, true);
            }
            catch (Exception e)
            {
                LoggingUtil.LogException(e);
            }
        }
 private void nextState()
 {
     stepTime = Time.fixedTime;
     currentState++;
     LoggingUtil.LogDebug(this, "Moved to state: " + currentState);
     CreateDelegates();
 }
Пример #5
0
        public override ExperienceTrait ConvertFrom <U>(U value)
        {
            LoggingUtil.LogDebug(this, StringBuilderCache.Format("ExperienceTraitParser.ConvertFrom<{0}>({1}", typeof(U), value));
            if (typeof(U) == typeof(string))
            {
                string sVal = (string)(object)value;

                if (HighLogic.CurrentGame == null)
                {
                    currentDataNode.SetDeterministic(currentKey, false);
                    return(null);
                }

                for (int index = 0; index < GameDatabase.Instance.ExperienceConfigs.Categories.Count; ++index)
                {
                    if (sVal == GameDatabase.Instance.ExperienceConfigs.Categories[index].Name)
                    {
                        Type type = KerbalRoster.GetExperienceTraitType(sVal) ?? typeof(ExperienceTrait);
                        return(ExperienceTrait.Create(type, GameDatabase.Instance.ExperienceConfigs.Categories[index], null));
                    }
                }

                throw new ArgumentException("'" + sVal + "' is not a valid experience trait.");
            }
            throw new DataStoreCastException(typeof(U), typeof(ExperienceTrait));
        }
Пример #6
0
        /// <summary>
        /// String statements work differently.  Basically it's just a search and replace for
        /// @identifier nodes, with the rest treated as a string literal.
        /// </summary>
        /// <returns>The full string after parsing</returns>
        internal override TResult ParseStatement <TResult>()
        {
            verbose &= LogEntryDebug <TResult>("ParseStatement");
            try
            {
                string value = "";
                while (expression.Length > 0)
                {
                    int   specialIdentifierIndex = expression.IndexOf("@");
                    Match m             = Regex.Match(expression, @"\s\w[\w\d]*\(");
                    int   functionIndex = m.Index;

                    if (m.Success && specialIdentifierIndex >= 0)
                    {
                        if (functionIndex < specialIdentifierIndex)
                        {
                            specialIdentifierIndex = -1;
                        }
                        else
                        {
                            functionIndex = -1;
                        }
                    }

                    if (m.Success)
                    {
                        value     += expression.Substring(0, functionIndex + 1);
                        expression = expression.Substring(functionIndex);
                        Token t = ParseToken();
                        LoggingUtil.LogDebug(this, "    " + t.sval);
                        value += ParseMethod <string>(t, null, true);
                    }
                    else if (specialIdentifierIndex >= 0)
                    {
                        value     += expression.Substring(0, specialIdentifierIndex);
                        expression = expression.Substring(specialIdentifierIndex);
                        value     += ParseSpecialIdentifier(ParseSpecialIdentifier());
                    }
                    else
                    {
                        value     += expression;
                        expression = "";
                    }
                }

                value = value.Replace("\\n", "\n");

                verbose &= LogExitDebug <TResult>("ParseStatement", value);
                return((TResult)(object)value);
            }
            catch
            {
                verbose &= LogException <TResult>("ParseStatement");
                throw;
            }
        }
Пример #7
0
        private void RemoveKerbals()
        {
            LoggingUtil.LogDebug(this, "Removing kerbals...");

            foreach (Kerbal kerbal in kerbals)
            {
                Kerbal.RemoveKerbal(kerbal);
            }
            kerbals.Clear();
        }
Пример #8
0
        private void Load()
        {
            ConfigNode[] experimentConfigs = GameDatabase.Instance.GetConfigNodes("CC_EXPERIMENT_DEFINITIONS");

            foreach (ConfigNode experimentConfig in experimentConfigs)
            {
                LoggingUtil.LogDebug(this, "Loading experiment definitions for " + experimentConfig.GetValue("name"));

                foreach (ConfigNode config in experimentConfig.GetNodes("EXPERIMENT"))
                {
                    string name = ConfigNodeUtil.ParseValue <string>(config, "name");
                    LoggingUtil.LogVerbose(this, "    loading experiment " + name);

                    ExperimentRules exp = new ExperimentRules(name);
                    experimentRules[name] = exp;

                    exp.ignored                 = ConfigNodeUtil.ParseValue <bool?>(config, "ignored", (bool?)false).Value;
                    exp.requireEVA              = ConfigNodeUtil.ParseValue <bool?>(config, "requireEVA", (bool?)false).Value;
                    exp.requireSurfaceSample    = ConfigNodeUtil.ParseValue <bool?>(config, "requireSurfaceSample", (bool?)false).Value;
                    exp.requireAsteroidTracking = ConfigNodeUtil.ParseValue <bool?>(config, "requireAsteroidTracking", (bool?)false).Value;
                    exp.requireAtmosphere       = ConfigNodeUtil.ParseValue <bool?>(config, "requireAtmosphere", (bool?)false).Value;
                    exp.requireNoAtmosphere     = ConfigNodeUtil.ParseValue <bool?>(config, "requireNoAtmosphere", (bool?)false).Value;
                    exp.requireSurface          = ConfigNodeUtil.ParseValue <bool?>(config, "requireSurface", (bool?)false).Value;
                    exp.requireNoSurface        = ConfigNodeUtil.ParseValue <bool?>(config, "requireNoSurface", (bool?)false).Value;
                    exp.disallowHomeSurface     = ConfigNodeUtil.ParseValue <bool?>(config, "disallowHomeSurface", (bool?)false).Value;
                    exp.disallowHomeFlying      = ConfigNodeUtil.ParseValue <bool?>(config, "disallowHomeFlying", (bool?)false).Value;
                    exp.disallowKSC             = ConfigNodeUtil.ParseValue <bool?>(config, "disallowKSC", (bool?)false).Value;
                    exp.partless                = ConfigNodeUtil.ParseValue <bool?>(config, "partless", (bool?)false).Value;
                    exp.part        = ConfigNodeUtil.ParseValue <List <string> >(config, "part", null);
                    exp.partModule  = ConfigNodeUtil.ParseValue <string>(config, "partModule", null);
                    exp.validBodies = ConfigNodeUtil.ParseValue <List <CelestialBody> >(config, "validBody", null);
                }

                // Add the experiment modules
                foreach (ConfigNode config in experimentConfig.GetNodes("MODULE"))
                {
                    string name = ConfigNodeUtil.ParseValue <string>(config, "name");
                    LoggingUtil.LogVerbose(this, "    loading module " + name);

                    experimentModules.Add(name);
                }
            }

            // Add experiment modules based on class
            foreach (Type expModule in ContractConfigurator.GetAllTypes <ModuleScienceExperiment>())
            {
                LoggingUtil.LogVerbose(this, "    adding module for class " + expModule.Name);
                experimentModules.AddUnique(expModule.Name);
            }

            loaded = true;
        }
Пример #9
0
        public IEnumerator <YieldInstruction> Burninator()
        {
            LoggingUtil.LogDebug(this, "burninating");
            while (burninating && FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.state != Vessel.State.DEAD)
            {
                Vessel v = FlightGlobals.ActiveVessel;
                v.srf_velocity        = -jool.GetSurfaceNVector(v.latitude, v.longitude);
                v.externalTemperature = 1000f;
                v.atmDensity          = 1.0f;
                v.speed = 3000f;
                v.mach  = 4f;

                yield return(new WaitForFixedUpdate());
            }
            LoggingUtil.LogDebug(this, "burninating done");
        }
        protected void CreateDelegates()
        {
            if (ParameterCount < 1)
            {
                LoggingUtil.LogDebug(this, "Adding EVA parameter...");
                evaParam = new ParameterDelegate <MonolithParameter>("Send a Kerbal on EVA", x => CheckParameters(MonolithState.STARTED));
                AddParameter(evaParam);

                LoggingUtil.LogDebug(this, "Adding approach parameter...");
                approachParam        = new ParameterDelegate <MonolithParameter>("", x => !approachParam.hidden && CheckParameters(MonolithState.EVA));
                approachParam.hidden = true;
                AddParameter(approachParam);

                LoggingUtil.LogDebug(this, "Adding 'full of stars' parameter...");
                fullofstarsParam        = new ParameterDelegate <MonolithParameter>("...it's full of stars!", x => !fullofstarsParam.hidden && CheckParameters(MonolithState.FULL_OF_STARS_FINAL));
                fullofstarsParam.hidden = true;
                AddParameter(fullofstarsParam);
            }

            bool changeMade = false;

            if (currentState >= MonolithState.EVA)
            {
                if (approachParam.hidden)
                {
                    LoggingUtil.LogDebug(this, "Unhiding approach parameter...");
                    approachParam.SetTitle("Approach the monolith with " + candidateName);
                    changeMade           = true;
                    approachParam.hidden = false;
                }
            }

            if (currentState >= MonolithState.FULL_OF_STARS1)
            {
                if (fullofstarsParam.hidden)
                {
                    LoggingUtil.LogDebug(this, "Unhiding 'full of stars' parameter...");
                    changeMade = true;
                    fullofstarsParam.hidden = false;
                }
            }

            if (changeMade)
            {
                ContractConfigurator.ContractConfigurator.OnParameterChange.Fire(Root, this);
            }
        }
        protected void DoAwarding()
        {
            IEnumerable <ProtoCrewMember> awardees = crew.Union(kerbals.Where(k => k.pcm != null).Select(k => k.pcm));

            LoggingUtil.LogDebug(this, "Awarding {0} points to {1} crew member(s)", experience, awardees.Count());

            // Set the homeworld
            if (homeworld == null)
            {
                homeworld = FlightGlobals.Bodies.Where(cb => cb.isHomeWorld).FirstOrDefault();
            }

            foreach (ProtoCrewMember pcm in awardees.Where(pcm => pcm != null))
            {
                LoggingUtil.LogVerbose(this, "    Awarding experience to {0}", pcm.name);

                // Find existing entries
                int currentValue = 2;
                foreach (FlightLog.Entry entry in pcm.careerLog.Entries.Concat(pcm.flightLog.Entries).Where(e => e.type.Contains(SPECIAL_XP)))
                {
                    // Get the entry with the largest value
                    int entryValue = Convert.ToInt32(entry.type.Substring(SPECIAL_XP.Length, entry.type.Length - SPECIAL_XP.Length));
                    currentValue = Math.Max(currentValue, entryValue);
                }

                // Can't go above 64 special experience
                int value = Math.Min(currentValue + experience, 64);

                // Increment the entry's experience value
                string type = SPECIAL_XP + value.ToString();

                // Do the awarding
                pcm.flightLog.AddEntry(type, homeworld.name);
                if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Assigned)
                {
                    pcm.ArchiveFlightLog();
                }
                else if (awardImmediately)
                {
                    pcm.experience     += experience;
                    pcm.experienceLevel = KerbalRoster.CalculateExperienceLevel(pcm.experience);
                }
            }

            // Prevent duplicate awards
            crew.Clear();
        }
Пример #12
0
        protected void OnFlightReady()
        {
            LoggingUtil.LogVerbose(this, "OnFlightReady");

            // Handle late adjustments to PQS City based waypoint positions (workaround for Kopernicus bug)
            foreach (WaypointData wpData in waypoints)
            {
                if (wpData.pqsCity != null)
                {
                    LoggingUtil.LogDebug(this, "Adjusting PQS City offset coordinates for waypoint {0}", wpData.waypoint.name);

                    CelestialBody body = FlightGlobals.Bodies.Where(b => b.name == wpData.waypoint.celestialName).First();
                    GeneratePQSCityCoordinates(wpData, body);
                    SetAltitude(wpData, body);
                    wpData.pqsCity = null;
                }
            }
        }
Пример #13
0
        protected override void TriggerAction()
        {
            foreach (KerbalInfo kerb in kerbalInfo)
            {
                if (kerb.kerbal.pcm != null)
                {
                    if (kerb.kerbalType != null)
                    {
                        LoggingUtil.LogDebug(this, "Setting type  of " + kerb.kerbal.name + " to " + kerb.kerbalType);
                        kerb.kerbal.pcm.type = kerb.kerbalType.Value;
                    }

                    if (!string.IsNullOrEmpty(kerb.trait))
                    {
                        LoggingUtil.LogDebug(this, "Setting trait of " + kerb.kerbal.name + " to " + kerb.trait);
                        KerbalRoster.SetExperienceTrait(kerb.kerbal.pcm, kerb.trait);
                    }
                }
                else
                {
                    LoggingUtil.LogWarning(this, "Couldn't change type of Kerbal " + kerb.kerbal.name + ", no ProtoCrewMember!");
                }
            }
        }
        protected void CreateVessels()
        {
            if (vesselsCreated)
            {
                return;
            }

            String gameDataDir = KSPUtil.ApplicationRootPath;

            gameDataDir = gameDataDir.Replace("\\", "/");
            if (!gameDataDir.EndsWith("/"))
            {
                gameDataDir += "/";
            }
            gameDataDir += "GameData";

            // Spawn the vessel in the game world
            foreach (VesselData vesselData in vessels)
            {
                LoggingUtil.LogVerbose(this, "Spawning a vessel named '" + vesselData.name + "'");

                // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB!
                ConfigNode currentShip = ShipConstruction.ShipConfig;

                ShipConstruct shipConstruct = ShipConstruction.LoadShip(gameDataDir + "/" + vesselData.craftURL);
                if (shipConstruct == null)
                {
                    LoggingUtil.LogError(this, "ShipConstruct was null when tried to load '" + vesselData.craftURL +
                                         "' (usually this means the file could not be found).");
                    continue;
                }

                // Restore ShipConstruction ship
                ShipConstruction.ShipConfig = currentShip;

                // Set the name
                if (string.IsNullOrEmpty(vesselData.name))
                {
                    vesselData.name = shipConstruct.shipName;
                }

                // Set some parameters that need to be at the part level
                uint flightId  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                uint missionID = (uint)Guid.NewGuid().GetHashCode();
                uint launchID  = HighLogic.CurrentGame.launchID++;
                foreach (Part p in shipConstruct.parts)
                {
                    p.flightID  = flightId;
                    p.missionID = missionID;
                    p.launchID  = launchID;
                    p.flagURL   = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL;
                }

                // Assign crew to the vessel
                foreach (CrewData cd in vesselData.crew)
                {
                    bool success = false;

                    // Find a seat for the crew
                    Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity);

                    // Add the crew member
                    if (part != null)
                    {
                        // Create the ProtoCrewMember
                        ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned);
                        if (cd.name != null)
                        {
                            crewMember.name = cd.name;
                        }

                        // Add them to the part
                        success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count);
                    }

                    if (!success)
                    {
                        LoggingUtil.LogWarning(this, "Unable to add crew to vessel named '" + vesselData.name + "'.  Perhaps there's no room?");
                        break;
                    }
                }

                // Set additional info for landed kerbals
                if (vesselData.landed)
                {
                    if (vesselData.altitude == null)
                    {
                        vesselData.altitude = LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body);
                    }

                    Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value);

                    vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body);
                    vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime());
                    LoggingUtil.LogDebug(this, "vesselData generated, orbit = " + vesselData.orbit);
                }

                // Create a dummy ProtoVessel, we will use this to dump the parts to a config node.
                // We can't use the config nodes from the .craft file, because they are in a
                // slightly different format than those required for a ProtoVessel (seriously
                // Squad?!?).
                ConfigNode  empty       = new ConfigNode();
                ProtoVessel dummyProto  = new ProtoVessel(empty, null);
                Vessel      dummyVessel = new Vessel();
                dummyVessel.parts    = shipConstruct.parts;
                dummyProto.vesselRef = dummyVessel;

                // Create the ProtoPartSnapshot objects and then initialize them
                foreach (Part p in shipConstruct.parts)
                {
                    dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
                }
                foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
                {
                    p.storePartRefs();
                }

                // Estimate an object class, numbers are based on the in game description of the
                // size classes.
                float size = shipConstruct.shipSize.magnitude / 2.0f;
                UntrackedObjectClass sizeClass;
                if (size < 4.0f)
                {
                    sizeClass = UntrackedObjectClass.A;
                }
                else if (size < 7.0f)
                {
                    sizeClass = UntrackedObjectClass.B;
                }
                else if (size < 12.0f)
                {
                    sizeClass = UntrackedObjectClass.C;
                }
                else if (size < 18.0f)
                {
                    sizeClass = UntrackedObjectClass.D;
                }
                else
                {
                    sizeClass = UntrackedObjectClass.E;
                }

                // Create the ship's parts
                ConfigNode[] partNodes = dummyProto.protoPartSnapshots.Select <ProtoPartSnapshot, ConfigNode>(GetNodeForPart).ToArray();

                // Create additional nodes
                ConfigNode[]    additionalNodes = new ConfigNode[1];
                DiscoveryLevels discoveryLevel  = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned;
                additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline);

                // Create the config node representation of the ProtoVessel
                ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes);

                // Additional seetings for a landed vessel
                if (vesselData.landed)
                {
                    // Create the config node representation of the ProtoVessel
                    protoVesselNode.SetValue("sit", Vessel.Situations.LANDED.ToString());
                    protoVesselNode.SetValue("landed", true.ToString());
                    protoVesselNode.SetValue("lat", vesselData.latitude.ToString());
                    protoVesselNode.SetValue("lon", vesselData.longitude.ToString());
                    protoVesselNode.SetValue("alt", vesselData.altitude.ToString());
                    protoVesselNode.SetValue("landedAt", vesselData.body.name);

                    // Figure out the additional heigh to subtract
                    float lowest = float.MaxValue;
                    foreach (Part p in shipConstruct.parts)
                    {
                        foreach (Collider collider in p.GetComponentsInChildren <Collider>())
                        {
                            if (collider.gameObject.layer != 21 && collider.enabled)
                            {
                                lowest = Mathf.Min(lowest, collider.bounds.min.y);
                            }
                        }
                    }

                    // Figure out the surface height and rotation
                    Vector3d   norm     = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude);
                    Quaternion rotation = Quaternion.FromToRotation(Vector3.forward, Vector3.up) *
                                          Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
                    protoVesselNode.SetValue("hgt", (shipConstruct.parts[0].localRoot.attPos0.y - lowest).ToString());
                    protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation));
                }

                // Add vessel to the game
                ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);

                // Store the id for later use
                vesselData.id = protoVessel.vesselRef.id;

                // Associate it so that it can be used in contract parameters
                ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef);
            }

            vesselsCreated = true;
        }
Пример #15
0
        public void Update()
        {
            // Wait for the strategy system to get loaded
            if (KSP.UI.Screens.Administration.Instance == null)
            {
                ticks = 0;
                return;
            }

            if (ticks++ == 0)
            {
                // Resize the root element that handles the width
                LoggingUtil.LogDebug(this, "Modifying width of admin screen...");
                Transform aspectFitter = KSP.UI.Screens.Administration.Instance.transform.FindDeepChild("bg and aspectFitter");
                if (aspectFitter != null)
                {
                    RectTransform rect = aspectFitter.GetComponent <RectTransform>();

                    // Determine the ideal size
                    int   count = Math.Max(StrategySystem.Instance.SystemConfig.Departments.Count - 4, 0);
                    float size  = Math.Min(944f + (count * 232.0f), Screen.width);

                    rect.sizeDelta = new Vector2(size, rect.sizeDelta.y);
                }

                // Clean up the strategy max text
                LoggingUtil.LogDebug(this, "Cleaning up strategy max text...");
                Transform       stratCountTransform = KSP.UI.Screens.Administration.Instance.transform.FindDeepChild("ActiveStratCount");
                TextMeshProUGUI stratCountText      = stratCountTransform.GetComponent <TextMeshProUGUI>();
                int             limit = Administration.Instance.MaxActiveStrategies - 1;
                if (!stratCountText.text.Contains("Max: " + limit))
                {
                    stratCountText.text = "Active Strategies: " + Administration.Instance.ActiveStrategyCount + " [Max: " + limit + "]";
                }

                // Replace department avatars with images when necessary
                LoggingUtil.LogDebug(this, "Performing department image replacement...");
                Transform scrollListKerbals = KSP.UI.Screens.Administration.Instance.transform.FindDeepChild("scroll list kerbals");
                foreach (DepartmentConfig department in StrategySystem.Instance.SystemConfig.Departments)
                {
                    // If there is no avatar prefab but there is a head image, use that in place
                    if (department.AvatarPrefab == null)
                    {
                        // Get the head image
                        Texture2D tex = department.HeadImage;
                        if (tex == null)
                        {
                            // Pull from texture DB if possible
                            if (GameDatabase.Instance.ExistsTexture(department.HeadImageString))
                            {
                                tex = GameDatabase.Instance.GetTexture(department.HeadImageString, false);
                            }
                            // Otherwise just load it
                            else
                            {
                                tex = TextureUtil.LoadTexture(department.HeadImageString);
                            }
                        }

                        for (int i = 0; i < scrollListKerbals.childCount; i++)
                        {
                            Transform      t = scrollListKerbals.GetChild(i);
                            KerbalListItem kerbalListItem = t.GetComponent <KerbalListItem>();
                            if (kerbalListItem.title.text.Contains(department.HeadName))
                            {
                                LoggingUtil.LogDebug(this, "Replacing admin building texture for department {0}", department.HeadName);
                                kerbalListItem.kerbalImage.texture  = tex;
                                kerbalListItem.kerbalImage.material = kerbalListItem.kerbalImage.defaultMaterial;

                                // Remove extra braces
                                if (kerbalListItem.title.text.Contains("()"))
                                {
                                    kerbalListItem.title.text.Replace("()", "");
                                }

                                break;
                            }
                        }
                    }
                }
            }
        }
Пример #16
0
        private IEnumerator <YieldInstruction> NovaCoroutine()
        {
            LoggingUtil.LogDebug(this, "Jool is going nova");
            state     = State.JOOL_SHRINK;
            joolScale = 1.0f;

            SetTransformed(false);

            // Get the AtmosphereFromGround object
            AtmosphereFromGround afg = Resources.FindObjectsOfTypeAll <AtmosphereFromGround>().
                                       Where(a => a != null && a.planet != null && a.planet.name == "Jool").First();

            // Capture original scaling info
            origScale       = jool.scaledBody.transform.localScale;
            origInnerRadius = afg.innerRadius;
            origOuterRadius = afg.outerRadius;
            origAtmoScale   = afg.transform.localScale;

            // Rescale over every iteration
            while (true)
            {
                // Check if this will be the last scaling operation
                bool lastIteration = joolScale <= SHRUNK_SCALE;
                if (lastIteration)
                {
                    joolScale = SHRUNK_SCALE;
                }

                // Rescale Jool's ScaledVersion Transform
                jool.scaledBody.transform.localScale = origScale * joolScale;

                // Rescale atmosphere
                afg.innerRadius          = origInnerRadius * joolScale;
                afg.outerRadius          = origOuterRadius * joolScale;
                afg.transform.localScale = origAtmoScale * joolScale;

                afg.KrESun              = afg.Kr * afg.ESun;
                afg.KmESun              = afg.Km * afg.ESun;
                afg.Kr4PI               = afg.Kr * 4f * (float)Math.PI;
                afg.Km4PI               = afg.Km * 4f * (float)Math.PI;
                afg.g2                  = afg.g * afg.g;
                afg.outerRadius2        = afg.outerRadius * afg.outerRadius;
                afg.innerRadius2        = afg.innerRadius * afg.innerRadius;
                afg.scale               = 1f / (afg.outerRadius - afg.innerRadius);
                afg.scaleDepth          = -0.25f;
                afg.scaleOverScaleDepth = afg.scale / afg.scaleDepth;

                afg.SetMaterial(true);

                yield return(null);

                if (lastIteration)
                {
                    break;
                }
            }

            // Do the transformation
            SetTransformed(true);

            // Add our extra stuff
            GameObject explosion = new GameObject("Explosion");

            explosion.transform.parent        = jool.scaledBody.transform;
            explosion.layer                   = jool.scaledBody.layer;
            explosion.transform.localScale    = Vector3.one * 1.01f;
            explosion.transform.localPosition = Vector3.zero;
            explosion.transform.localRotation = Quaternion.identity;
            MeshRenderer explosionRenderer = explosion.AddComponent <MeshRenderer>();

            foreach (FieldInfo field in typeof(MeshRenderer).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                field.SetValue(explosionRenderer, field.GetValue(jool.scaledBody.GetComponent <MeshRenderer>()));
            }
            Texture2D explosionTex = TextureUtil.LoadTexture("ContractPacks/JoolianEncounter/Images/explosion.dds.noload");

            explosionRenderer.material.shader = Shader.Find("KSP/Alpha/Translucent");
            explosionRenderer.material.SetTexture(Shader.PropertyToID("_MainTex"), explosionTex);
            MeshFilter explosionMesh = explosion.AddComponent <MeshFilter>();

            explosionMesh.sharedMesh = jool.scaledBody.GetComponent <MeshFilter>().sharedMesh;
            explosion.SetActive(true);

            // Rescale over every iteration
            joolScale = SHRUNK_SCALE;
            state     = State.SUN_GROW;
            stateTime = Time.time;
            while (true)
            {
                // Check if this will be the last scaling operation
                bool lastIteration = joolScale >= FINAL_SCALE;
                if (lastIteration)
                {
                    joolScale = FINAL_SCALE;
                }

                // Rescale Jool's scaled body Transform
                jool.scaledBody.transform.localScale = origScale * joolScale;

                // Fade the alpha out as the explosion grows
                float alpha = Mathf.Lerp(1.0f, 0.0f, (explosionScale / joolScale) / 10.0f);
                explosionRenderer.material.color = new Color(1.0f, 1.0f, 1.0f, alpha);

                // Rescale the explosion
                explosion.transform.localScale = Vector3.one * (explosionScale / joolScale);

                if (lastIteration)
                {
                    break;
                }
                yield return(null);
            }

            // Continue with the outer part of the explosion
            state          = State.EXPLOSION_GROW;
            explosionsDone = false;
            while (true)
            {
                // Rescale the explosion
                explosion.transform.localScale = Vector3.one * (explosionScale / joolScale);

                // Stop burninating 5000 km after it has passed
                if ((explosionScale / joolScale) * 1.01f * jool.Radius >= FlightGlobals.ActiveVessel.altitude + jool.Radius + 5000000)
                {
                    burninating = false;
                }
                // There's a big delay before the atmospheric effects kick in, so start burninating pretty early (5000 km)
                else if (!burninating && (explosionScale / joolScale) * jool.Radius >= FlightGlobals.ActiveVessel.altitude + jool.Radius - 5000000)
                {
                    burninating = true;
                    StartCoroutine(Burninator());
                }

                // Blow up the ship! (part of it)
                if (!explosionsDone && (explosionScale / joolScale) * jool.Radius >= FlightGlobals.ActiveVessel.altitude + jool.Radius)
                {
                    ExplodeParts();

                    // Do a camera wobble
                    LoggingUtil.LogDebug(this, "overheat event");
                    FlightCameraFX fcfx        = UnityEngine.Object.FindObjectOfType <FlightCameraFX>();
                    MethodInfo     eventMethod = typeof(FlightCameraFX).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).
                                                 Where(mi => mi.Name == "OnVesselEvent").First();
                    eventMethod.Invoke(fcfx, new object[] { new EventReport(FlightEvents.OVERHEAT, FlightGlobals.ActiveVessel.rootPart,
                                                                            FlightGlobals.ActiveVessel.name, "Jool") });
                }

                // Fade the alpha out as the explosion grows
                float alpha = Mathf.Lerp(1.0f, 0.0f, (explosionScale / joolScale) / 10.0f);
                explosionRenderer.material.color = new Color(1.0f, 1.0f, 1.0f, alpha);

                if ((explosionScale / joolScale) >= 10.0f)
                {
                    break;
                }
                yield return(null);
            }

            // Remove explodey part
            burninating = false;
            explosion.transform.parent = null;
            Destroy(explosion);
            Destroy(explosionTex);
        }
Пример #17
0
        public void Start()
        {
            LoggingUtil.LogVerbose(this, "Start");

            // Don't run if not in career
            if (!HighLogic.CurrentGame.scenarios.Any(sm => sm.moduleName == "ContractConfiguratorSettings"))
            {
                LoggingUtil.LogDebug(this, "Destroying TrackingStationUI - not in career mode.");
                Destroy(this);
                return;
            }

            // Get the last button in the list to use as a copy
            MapViewFiltering.FilterButton lastButton = MapViewFiltering.Instance.FilterButtons.Last();

            // Create our copies
            activeWaypointButton       = UnityEngine.Object.Instantiate(lastButton.button.gameObject);
            activeWaypointButton.name  = "Button Active Waypoints";
            offeredWaypointButton      = UnityEngine.Object.Instantiate(lastButton.button.gameObject);
            offeredWaypointButton.name = "Button Offered Waypoints";
            activeOrbitButton          = UnityEngine.Object.Instantiate(lastButton.button.gameObject);
            activeOrbitButton.name     = "Button Active Orbits";
            offeredOrbitButton         = UnityEngine.Object.Instantiate(lastButton.button.gameObject);
            offeredOrbitButton.name    = "Button Offered Orbits";

            // Fix z coordinates
            activeWaypointButton.GetComponent <RectTransform>().SetLocalPositionZ(750);
            offeredWaypointButton.GetComponent <RectTransform>().SetLocalPositionZ(750);
            activeOrbitButton.GetComponent <RectTransform>().SetLocalPositionZ(750);
            offeredOrbitButton.GetComponent <RectTransform>().SetLocalPositionZ(750);

            // Set up the tool-tips
            activeWaypointButton.GetComponent <TooltipController_Text>().textString  = "Toggle Active Waypoints";
            offeredWaypointButton.GetComponent <TooltipController_Text>().textString = "Toggle Offered Waypoints";
            activeOrbitButton.GetComponent <TooltipController_Text>().textString     = "Toggle Active Orbits";
            offeredOrbitButton.GetComponent <TooltipController_Text>().textString    = "Toggle Offered Orbits";

            // Setup the button
            TrackingStationObjectButton activeWaypointTSButton  = activeWaypointButton.GetComponent <TrackingStationObjectButton>();
            TrackingStationObjectButton offeredWaypointTSButton = offeredWaypointButton.GetComponent <TrackingStationObjectButton>();
            TrackingStationObjectButton activeOrbitTSButton     = activeOrbitButton.GetComponent <TrackingStationObjectButton>();
            TrackingStationObjectButton offeredOrbitTSButton    = offeredOrbitButton.GetComponent <TrackingStationObjectButton>();

            // Setup handlers
            activeWaypointTSButton.OnClickLeft.AddListener(new UnityAction(ActiveWaypointButtonClick));
            activeWaypointTSButton.OnClickRight.AddListener(new UnityAction(ActiveWaypointButtonClick));
            offeredWaypointTSButton.OnClickLeft.AddListener(new UnityAction(OfferedWaypointButtonClick));
            offeredWaypointTSButton.OnClickRight.AddListener(new UnityAction(OfferedWaypointButtonClick));
            activeOrbitTSButton.OnClickLeft.AddListener(new UnityAction(ActiveOrbitButtonClick));
            activeOrbitTSButton.OnClickRight.AddListener(new UnityAction(ActiveOrbitButtonClick));
            offeredOrbitTSButton.OnClickLeft.AddListener(new UnityAction(OfferedOrbitButtonClick));
            offeredOrbitTSButton.OnClickRight.AddListener(new UnityAction(OfferedOrbitButtonClick));

            // Setup sprites
            activeWaypointTSButton.spriteTrue   = activeWaypointEnabledSprite;
            activeWaypointTSButton.spriteFalse  = activeWaypointDisabledSprite;
            offeredWaypointTSButton.spriteTrue  = offeredWaypointEnabledSprite;
            offeredWaypointTSButton.spriteFalse = offeredWaypointDisabledSprite;
            activeOrbitTSButton.spriteTrue      = activeOrbitEnabledSprite;
            activeOrbitTSButton.spriteFalse     = activeOrbitDisabledSprite;
            offeredOrbitTSButton.spriteTrue     = offeredOrbitEnabledSprite;
            offeredOrbitTSButton.spriteFalse    = offeredOrbitDisabledSprite;

            // Set defaults
            activeWaypointButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayActiveWaypoints);
            offeredWaypointButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayOfferedWaypoints);
            activeOrbitButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayActiveOrbits);
            offeredOrbitButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayOfferedOrbits);

            // Disable counts
            activeWaypointButton.GetChild("Count").SetActive(false);
            offeredWaypointButton.GetChild("Count").SetActive(false);
            activeOrbitButton.GetChild("Count").SetActive(false);
            offeredOrbitButton.GetChild("Count").SetActive(false);

            // Re-parent
            GameObject    trackingFilters     = lastButton.button.transform.parent.gameObject;
            RectTransform trackingFiltersRect = trackingFilters.GetComponent <RectTransform>();

            trackingFiltersRect.sizeDelta = new Vector2(trackingFiltersRect.sizeDelta.x + 44 * 2, trackingFiltersRect.sizeDelta.y);
            activeWaypointButton.transform.SetParent(trackingFilters.transform);
            offeredWaypointButton.transform.SetParent(trackingFilters.transform);
            activeOrbitButton.transform.SetParent(trackingFilters.transform);
            offeredOrbitButton.transform.SetParent(trackingFilters.transform);
            activeWaypointButton.SetActive(true);
            offeredWaypointButton.SetActive(true);
            activeOrbitButton.SetActive(true);
            offeredOrbitButton.SetActive(true);

            LoggingUtil.LogVerbose(this, "Finished setup");
        }
 void Start()
 {
     LoggingUtil.LogDebug(typeof(MonolithParameter), "VelocityHandler startup");
 }
        protected bool CheckParameters(MonolithState paramState)
        {
            if (paramState < currentState)
            {
                return(true);
            }

            // StarJeb not active vessel
            if (starJeb != null && FlightGlobals.ActiveVessel != starJeb ||
                candidate != null && FlightGlobals.ActiveVessel != candidate)
            {
                stepTime = Time.fixedTime;
                return(false);
            }

            // Create the velocity change handler
            if (velHdlr == null)
            {
                LoggingUtil.LogDebug(this, "Adding VelocityHandler");
                velHdlr       = MapView.MapCamera.gameObject.AddComponent <VelocityHandler>();
                velHdlr.param = this;
            }

            switch (currentState)
            {
            case MonolithState.STARTED:
                // Look for an eva
                if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.vesselType == VesselType.EVA)
                {
                    candidate     = FlightGlobals.ActiveVessel;
                    candidateName = candidate.vesselName;
                    LoggingUtil.LogDebug(this, "Got an eva, starJeb = " + candidate.vesselName);
                    nextState();
                    return(true);
                }
                return(false);

            case MonolithState.EVA:
            {
                Vessel discovery         = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One");
                float  discoveryDistance = discovery == null ? 10000 : Vector3.Distance(discovery.transform.position, candidate.transform.position);

                if (distance < 10000 && discoveryDistance > distance && Time.fixedTime - stepTime > 10.0f || distance < MONOLITH_TOO_CLOSE)
                {
                    // Store Star Jeb's name
                    starJeb     = candidate;
                    starJebName = candidateName;
                    PersistentDataStore.Instance.Store <string>("starJebName", starJebName);

                    // Store Star Jeb's friend's name
                    ProtoCrewMember protoStarJeb = candidate.GetVesselCrew().First();
                    if (discovery != null)
                    {
                        string          trait      = protoStarJeb.experienceTrait.TypeName == "Scientist" ? "Pilot" : "Scientist";
                        ProtoCrewMember notStarJeb = discovery.GetVesselCrew().Where(pcm => pcm.experienceTrait.TypeName == trait).FirstOrDefault();
                        if (notStarJeb != null)
                        {
                            PersistentDataStore.Instance.Store <string>("notStarJebName", notStarJeb.name);
                        }
                    }
                    candidate = null;
                    nextState();

                    // Set the right image (male vs. female) for the end sequence
                    ConfiguredContract contract  = Root as ConfiguredContract;
                    DialogBox          dialogBox = contract.Behaviours.Select(b => b as DialogBox).Where(b => b != null).FirstOrDefault();
                    if (dialogBox != null)
                    {
                        FieldInfo detailsField = typeof(DialogBox).GetFields(BindingFlags.Instance | BindingFlags.NonPublic).
                                                 Where(fi => fi.FieldType == typeof(List <DialogBox.DialogDetail>)).First();
                        DialogBox.DialogDetail detail       = ((List <DialogBox.DialogDetail>)detailsField.GetValue(dialogBox)).First();
                        DialogBox.ImageSection starJebImage = detail.sections.First() as DialogBox.ImageSection;
                        starJebImage.imageURL = protoStarJeb.gender == ProtoCrewMember.Gender.Male ?
                                                "ContractPacks/AnomalySurveyor/Images/starjeb.dds.noload" :
                                                "ContractPacks/AnomalySurveyor/Images/starjeb_female.dds.noload";
                    }

                    return(true);
                }
            }
                return(false);

            case MonolithState.FULL_OF_STARS1:
            {
                // Backup progress tracking
                progressTreeBackup = new ConfigNode("PROGRESS_TREE_BACKUP");
                ProgressTracking.Instance.OnSave(progressTreeBackup);

                // Give the first kick away from Jool - this one using regular velocity change
                CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First();

                // Find closest point on the jool-monolith line, and throw us away from that (so we don't hit either)
                Vector3 line    = monolith.transform.position - jool.transform.position;
                float   t       = Vector3.Dot(line, (starJeb.transform.position - jool.transform.position)) / Vector3.Dot(line, line);
                Vector3 closest = jool.transform.position + line * t;

                velocity  = (starJeb.transform.position - (t > 1.0 ? jool.transform.position : closest)).normalized;
                velocity += new Vector3(0.0f, 0.1f, 0.0f);
                velocity *= 15000;
                LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity);
                nextState();

                // Camera to target jool
                FlightCamera.SetTarget(starJeb.transform);
                FlightCamera.fetch.SetCamCoordsFromPosition((starJeb.transform.position - jool.transform.position).normalized * 25.0f);
            }
                return(false);

            case MonolithState.FULL_OF_STARS2:
                if (Time.fixedTime - stepTime > 4.0f)
                {
                    // Give the second kick away from Jool - these using anti-kraken velocity change
                    CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First();
                    velocity  = (starJeb.transform.position - jool.transform.position).normalized;
                    velocity += new Vector3(0.0f, 0.1f, 0.0f);
                    velocity *= 1500000;
                    LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity);
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS3:
                if (Time.fixedTime - stepTime > 3.0f)
                {
                    // Give the third kick away from Jool
                    CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First();
                    velocity  = (starJeb.transform.position - jool.transform.position).normalized;
                    velocity *= 20000000;
                    LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity);
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS4:
                if (Time.fixedTime - stepTime > 2.0f)
                {
                    // Give the fourth and final kick away from Jool
                    CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First();
                    velocity  = (starJeb.transform.position - jool.transform.position).normalized;
                    velocity *= 200000000;
                    LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity);
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS5:
                if (Time.fixedTime - stepTime > 2.0f)
                {
                    // Move along
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_DRES1:
            {
                // Visit Dres
                CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First();

                // Determine which side the sun is on - makes for a better show
                CelestialBody sun       = FlightGlobals.Bodies.Where(b => b.name == "Sun").First();
                Vector3       sunnySide = sun.transform.position - dres.transform.position;
                sunnySide.x = 0.0f;
                sunnySide.y = 1;         // Move across the top of the planet
                sunnySide.z = Math.Sign(sunnySide.z);

                // Set position for starjeb
                float distance = 4.0f * (float)dres.Radius;
                starJeb.SetPosition(dres.transform.position + new Vector3(distance, (float)dres.Radius, (float)dres.Radius * sunnySide.z));

                velocity  = (dres.transform.position - starJeb.transform.position + sunnySide * ((float)dres.Radius)).normalized;
                velocity *= distance / 3.0f;
                LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity);
                starJeb.SetWorldVelocity(dres.getRFrmVel(starJeb.transform.position));
                nextState();
            }
                return(false);

            case MonolithState.FULL_OF_STARS_DRES2:
            {
                // Camera to target Dres - do this on a seperate update to allow KSP to catch up
                CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First();
                FlightCamera.SetTarget(starJeb.transform);
                FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - dres.transform.position).normalized * 10.0f);

                // Make sure that the camera gets fixed
                if (Time.fixedTime - stepTime > 0.1f)
                {
                    nextState();
                }
            }
                return(false);

            case MonolithState.FULL_OF_STARS_DRES3:
                if (Time.fixedTime - stepTime > 5.5f)
                {
                    // Done with Dres
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_DUNA1:
            {
                // Start between the sun and Duna
                CelestialBody duna      = FlightGlobals.Bodies.Where(b => b.name == "Duna").First();
                CelestialBody sun       = FlightGlobals.Bodies.Where(b => b.name == "Sun").First();
                Vector3       sunnySide = sun.transform.position - duna.transform.position;
                sunnySide.Normalize();

                // Set us up a nice 4 radiuses away...
                float distance = 4.0f * (float)duna.Radius;
                starJeb.SetPosition(duna.transform.position + sunnySide * distance);

                // Go straight at Duna
                velocity  = (duna.transform.position - starJeb.transform.position).normalized;
                velocity *= distance / 3.0f;
                LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity);

                // Now offset him down so he doesn't actually hit Duna...
                starJeb.SetPosition(starJeb.transform.position + new Vector3(0.0f, -((float)duna.Radius + 55000), 0.0f));
                starJeb.SetWorldVelocity(duna.getRFrmVel(starJeb.transform.position));

                nextState();
            }
                return(false);

            case MonolithState.FULL_OF_STARS_DUNA2:
            {
                // Camera to target Duna - do this on a seperate update to allow KSP to catch up
                CelestialBody duna = FlightGlobals.Bodies.Where(b => b.name == "Duna").First();
                FlightCamera.SetTarget(starJeb.transform);
                FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - duna.transform.position).normalized * 25.0f);

                // Make sure that the camera gets fixed
                if (Time.fixedTime - stepTime > 0.1f)
                {
                    nextState();
                }
            }
                return(false);

            case MonolithState.FULL_OF_STARS_DUNA3:
                if (Time.fixedTime - stepTime > 5.5f)
                {
                    // Done with Duna
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_EELOO1:
            {
                // Start perpendicular to the sun and Eeloo
                CelestialBody eeloo = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First();
                CelestialBody sun   = FlightGlobals.Bodies.Where(b => b.name == "Sun").First();
                Vector3       perp  = eeloo.transform.position - sun.transform.position;
                float         tmp   = perp.x;
                perp.x = -perp.z;
                perp.z = tmp;
                perp.Normalize();

                // Set us up a nice 4 radiuses away...
                float distance = 4.0f * (float)eeloo.Radius;
                starJeb.SetPosition(eeloo.transform.position + perp * distance);

                // Determine which side the sun is on - makes for a better show
                Vector3 sunnySide = sun.transform.position - eeloo.transform.position;
                sunnySide.Normalize();

                // Go straight at Eeloo
                velocity  = (eeloo.transform.position - starJeb.transform.position).normalized;
                velocity *= distance / 3.0f;
                LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity);

                // Now offset him down so he doesn't actually hit Eeloo...
                starJeb.SetPosition(starJeb.transform.position + sunnySide * ((float)eeloo.Radius * 1.5f));
                starJeb.SetWorldVelocity(eeloo.getRFrmVel(starJeb.transform.position));

                nextState();
            }
                return(false);

            case MonolithState.FULL_OF_STARS_EELOO2:
            {
                // This time won't target directly towards Eeloo, as the player will have some idea
                // what is up by now.
                CelestialBody eeloo       = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First();
                CelestialBody sun         = FlightGlobals.Bodies.Where(b => b.name == "Sun").First();
                Vector3       awayFromSun = sun.transform.position - eeloo.transform.position;
                awayFromSun.Normalize();

                FlightCamera.SetTarget(starJeb.transform);
                FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromSun * 50.0f);

                // Make sure that the camera gets fixed
                if (Time.fixedTime - stepTime > 0.1f)
                {
                    nextState();
                }
            }
                return(false);

            case MonolithState.FULL_OF_STARS_EELOO3:
                if (Time.fixedTime - stepTime > 5.5f)
                {
                    velocity = null;

                    // Done with Eeloo
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_EVE1:
            {
                CelestialBody eve            = FlightGlobals.Bodies.Where(b => b.name == "Eve").First();
                Vector3       targetPosition = Destination.Value;
                Vector3       normal         = eve.GetSurfaceNVector(eveLatitude, eveLongitude);
                startDistance = 10000000f;
                Vector3 start = targetPosition + normal * startDistance;

                starJeb.SetPosition(start);
                nextState();
            }
                return(false);

            case MonolithState.FULL_OF_STARS_EVE2:
            {
                // Camera straight towards Eve - we're going in!
                CelestialBody eve         = FlightGlobals.Bodies.Where(b => b.name == "Eve").First();
                Vector3       awayFromEve = starJeb.transform.position - eve.transform.position;
                awayFromEve.Normalize();

                FlightCamera.SetTarget(starJeb.transform);
                FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromEve * 15.0f);

                // Make sure that the camera gets fixed
                if (Time.fixedTime - stepTime > 0.1f)
                {
                    nextState();
                }
            }
                return(false);

            case MonolithState.FULL_OF_STARS_EVE3:
                // Wait until we've held the position for a split second
                if (Time.fixedTime - stepTime >= 9.3f)
                {
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_EVE4:
                // Give the player a bit to get settled, then let the fun begins
                if (Time.fixedTime - stepTime >= 15.0f)
                {
                    // Spawn some asteroids
                    CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First();
                    ScenarioDiscoverableObjects asteroidSpawner = (ScenarioDiscoverableObjects)HighLogic.CurrentGame.scenarios.Find(
                        s => s.moduleRef is ScenarioDiscoverableObjects).moduleRef;
                    System.Random random = new System.Random();

                    // Spawn some more asteroids
                    for (int i = 0; i < ASTEROID_COUNT; i++)
                    {
                        asteroidSpawner.SpawnAsteroid();
                    }

                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_EVE5:
                // Wait a full second after spawning the asteroids - we're not allowed to pull
                // them off rails until they've been active a bit
                if (Time.fixedTime - stepTime > 1.0f)
                {
                    // Spawn some asteroids
                    CelestialBody eve    = FlightGlobals.Bodies.Where(b => b.name == "Eve").First();
                    System.Random random = new System.Random();

                    foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT))
                    {
                        // Set the position
                        double r         = random.NextDouble() * 0.02 + 0.002;
                        double theta     = random.NextDouble() * 2.0 * Math.PI;
                        double latitude  = starJeb.latitude + r * Math.Sin(theta);
                        double longitude = starJeb.longitude + r * Math.Cos(theta);
                        double altitude  = starJeb.altitude + 100 + random.NextDouble() * 200;
                        asteroid.SetPosition(eve.GetWorldSurfacePosition(latitude, longitude, altitude));
                        asteroid.ChangeWorldVelocity(asteroid.GetSrfVelocity());
                        asteroid.Load();
                        asteroid.GoOffRails();
                    }
                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_EVE6:
            {
                // Determine if there's an asteroid about to kill us
                CelestialBody eve            = FlightGlobals.Bodies.Where(b => b.name == "Eve").First();
                bool          killerAsteroid = FlightGlobals.Vessels.Where(v => v.mainBody == eve && v.vesselType == VesselType.SpaceObject &&
                                                                           Vector3.Distance(starJeb.transform.position, v.transform.position) < 5.5 * ((int)v.DiscoveryInfo.objectSize + 1)).Any();

                if (killerAsteroid || Time.fixedTime - stepTime > 20.0f)
                {
                    foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT))
                    {
                        asteroid.Die();
                    }
                    nextState();
                }
            }
                return(false);

            case MonolithState.FULL_OF_STARS_KERBIN1:
            {
                CheatOptions.NoCrashDamage = false;

                // Start between the sun and Kerbin
                CelestialBody kerbin    = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First();
                CelestialBody sun       = FlightGlobals.Bodies.Where(b => b.name == "Sun").First();
                Vector3       sunnySide = sun.transform.position - kerbin.transform.position;
                sunnySide.Normalize();

                // Set us up a nice 4 radiuses away...
                float distance = 4.0f * (float)kerbin.Radius;
                starJeb.SetPosition(kerbin.transform.position + sunnySide * distance);

                // Orient him properly
                KerbalEVA  keva           = starJeb.FindPartModulesImplementing <KerbalEVA>().First();
                MethodInfo rotationMethod = typeof(KerbalEVA).GetMethod("correctGroundedRotation", BindingFlags.Instance | BindingFlags.NonPublic);
                starJeb.packed = true;
                rotationMethod.Invoke(keva, new object[] { });
                starJeb.packed = false;

                // Hardcode an orbital velocity, because it's late and I'm tired
                starJeb.SetWorldVelocity(kerbin.getRFrmVel(starJeb.transform.position).normalized * 1085);

                nextState();
            }
                return(false);

            case MonolithState.FULL_OF_STARS_KERBIN2:
            {
                // Camera to target kerbin - do this on a seperate update to allow KSP to catch up
                CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First();
                FlightCamera.SetTarget(starJeb.transform);
                FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 10.0f);

                starJeb.SetRotation(FlightCamera.fetch.transform.rotation * Quaternion.AngleAxis(180.0f, FlightCamera.fetch.transform.up));

                // Make sure that the camera gets fixed
                if (Time.fixedTime - stepTime > 0.1f)
                {
                    nextState();
                }
            }
                return(false);

            case MonolithState.FULL_OF_STARS_KERBIN3:
                if (Time.fixedTime - stepTime > 2.0f)
                {
                    // Turn into star jeb
                    CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First();

                    starJeb.vesselName = "The Star Jeb";
                    Undress(starJeb.gameObject);
                    FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 1.5f);

                    nextState();
                }
                return(false);

            case MonolithState.FULL_OF_STARS_KERBIN4:
                if (Time.fixedTime - stepTime < 15.0f)
                {
                    CelestialBody kerbin       = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First();
                    Vector3       camDirection = starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized;
                }
                else
                {
                    nextState();

                    monolith.Die();
                    monolith = null;

                    starJeb.Die();
                    starJeb = null;

                    Vessel discovery = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One");
                    FlightGlobals.ForceSetActiveVessel(discovery);
                }
                return(false);

            case MonolithState.FULL_OF_STARS_FINAL:
                nextState();
                return(true);

            default:
                return(false);
            }
        }