Пример #1
0
 new static public SimulatedParachute New(ModuleParachute mp, ReentrySimulation.SimCurves simCurve, double startTime, int limitChutesStage)
 {
     SimulatedParachute part = new SimulatedParachute();
     part.Set(mp.part, simCurve);
     part.Set(mp, startTime, limitChutesStage);
     return part;
 }
 public static SimulatedParachute Borrow(ModuleParachute mp, ReentrySimulation.SimCurves simCurve, double startTime, int limitChutesStage)
 {
     SimulatedParachute part = pool.Borrow();
     part.Init(mp.part, simCurve);
     part.Init(mp, startTime, limitChutesStage);
     return part;
 }
Пример #3
0
        public void Set(ModuleParachute mp, double startTime, int limitChutesStage)
        {
            this.para = mp;
            this.state = mp.deploymentState;

            willDeploy = limitChutesStage != -1 && para.part.inverseStage >= limitChutesStage;

            // Work out when the chute was put into its current state based on the current drag as compared to the stowed, semi deployed and fully deployed drag

            double timeSinceDeployment = 0;
            
            switch (mp.deploymentState)
            {
                case ModuleParachute.deploymentStates.SEMIDEPLOYED:
                    if (mp.Anim.isPlaying)
                        timeSinceDeployment = mp.Anim[mp.semiDeployedAnimation].time;
                    else
                        timeSinceDeployment = 10000000;
                    break;

                case ModuleParachute.deploymentStates.DEPLOYED:
                    if (mp.Anim.isPlaying)
                        timeSinceDeployment = mp.Anim[mp.fullyDeployedAnimation].time;
                    else
                        timeSinceDeployment = 10000000;
                    break;

                case ModuleParachute.deploymentStates.STOWED:
                case ModuleParachute.deploymentStates.ACTIVE:
                    // If the parachute is stowed then for some reason para.parachuteDrag does not reflect the stowed drag. set this up by hand. 
                    timeSinceDeployment = 10000000;
                    break;

                default:
                    // otherwise set the time since deployment to be a very large number to indcate that it has been in that state for a long time (although we do not know how long!
                    timeSinceDeployment = 10000000;
                    break;
            }

            this.openningTime = startTime - timeSinceDeployment;

            //Debug.Log("Parachute " + para.name + " parachuteDrag:" + this.parachuteDrag + " stowedDrag:" + para.stowedDrag + " semiDeployedDrag:" + para.semiDeployedDrag + " fullyDeployedDrag:" + para.fullyDeployedDrag + " part.maximum_drag:" + para.part.maximum_drag + " part.minimum_drag:" + para.part.minimum_drag + " semiDeploymentSpeed:" + para.semiDeploymentSpeed + " deploymentSpeed:" + para.deploymentSpeed + " deploymentState:" + para.deploymentState + " timeSinceDeployment:" + timeSinceDeployment);
            // Keep that test code until they fix the bug in the new parachute module
            //if ((realDrag / parachuteDrag) > 1.01d || (realDrag / parachuteDrag) < 0.99d)
            //    Debug.Log("Parachute " + para.name + " parachuteDrag:" + this.parachuteDrag.ToString("F3") + " RealDrag:" + realDrag.ToString("F3") + " MinDrag:" + para.part.minimum_drag.ToString("F3") + " MaxDrag:" + para.part.maximum_drag.ToString("F3"));
        }
		public override void OnStart(StartState state)
		{
			base.OnStart(state);

			this.chuteModule = base.part.getFirstModuleOfType<ModuleParachute>();
			ModuleParachute prefabChuteModule = base.part.partInfo.partPrefab.getFirstModuleOfType<ModuleParachute>();

			if (this.chuteModule == null)
			{
				return;
			}

			this.prefabDeploySpeed = prefabChuteModule.deploymentSpeed;
			this.prefabSemiDeploySpeed = prefabChuteModule.semiDeploymentSpeed;

			this.chuteModule.Fields["deploymentSpeed"].guiActiveEditor = true;
			this.chuteModule.Fields["deploymentSpeed"].guiName = "Deploy Spd";
			this.chuteModule.Fields["deploymentSpeed"].guiFormat = "G3";

			this.chuteModule.Fields["semiDeploymentSpeed"].guiActiveEditor = true;
			this.chuteModule.Fields["semiDeploymentSpeed"].guiName = "Semi-Deploy Spd";
			this.chuteModule.Fields["semiDeploymentSpeed"].guiFormat = "G3";

			var deployField = this.Fields["deploymentFactor"].uiControlCurrent() as UI_FloatRange;
			var semiDeployField = this.Fields["semiDeploymentFactor"].uiControlCurrent() as UI_FloatRange;

			float step;

			if (this.maxFactor >= 5f)
			{
				step = Mathf.Round(Mathf.Pow(10f, (int)Mathf.Log10(this.maxFactor) - 1)) / 2f;
			}
			else
			{
				step = 0.1f;
			}

			deployField.maxValue = this.maxFactor;
			deployField.minValue = 1f;
			deployField.stepIncrement = step;

			semiDeployField.maxValue = this.maxFactor;
			semiDeployField.minValue = 1f;
			deployField.stepIncrement = step;
		}
Пример #5
0
        protected override void DI_Start(StartState state)
        {
            chute = this.part.Modules.OfType <ModuleParachute>().Single();

            foreach (Part part_each in this.part.vessel.Parts)               //Make sure that there is at least one other chute on the craft!
            {
                if (part_each != this.part)
                {
                    foreach (PartModule module_each in part_each.Modules)
                    {
                        if (module_each is ModuleParachute)
                        {
                            this.canFail = true;
                        }
                    }
                }
            }
        }
Пример #6
0
 public override void OnAwake()
 {
     base.OnAwake();
     if (part && part.Modules != null) // thanks, FlowerChild!
     {
         is_engine = (part.Modules.Contains("ModuleEngines") || part.Modules.Contains("ModuleEnginesFX"));
         is_eva    = part.Modules.Contains("KerbalEVA");
         if (part.Modules.Contains("ModuleParachute"))
         {
             parachute = (ModuleParachute)part.Modules["ModuleParachute"];
         }
         if (part.Modules.Contains("RealChuteModule"))
         {
             realChute = part.Modules["RealChuteModule"];
             rCType    = realChute.GetType();
         }
     }
 }
        public void StartPlanning()
        {
            // what is the highest point at which we could semi deploy? - look at all the parachutes in the craft, and consider the lowest semi deployment pressure.
            float minSemiDeployPressure = 0;
            float maxFullDeployHeight   = 0;

            parachutePresent = false; // First assume that there are no parachutes.

            // TODO should we check if each of these parachutes is withing the staging limit?
            for (int i = 0; i < autoPilot.vesselState.parachutes.Count; i++)
            {
                ModuleParachute p = autoPilot.vesselState.parachutes[i];
                if (p.minAirPressureToOpen > minSemiDeployPressure)
                // Although this is called "minSemiDeployPressure" we want to find the largest value for each of our parachutes. This can be used to calculate the corresponding height, and hence a height at which we can be guarenteed that all our parachutes will deploy if asked to.
                {
                    minSemiDeployPressure = p.minAirPressureToOpen;
                }
                if (p.deployAltitude > maxFullDeployHeight)
                {
                    maxFullDeployHeight = p.deployAltitude;
                }

                parachutePresent = true;
            }

            // If parachutes are present on the craft then work out the max / min semideployment heights and the starting value.
            if (parachutePresent)
            {
                // TODO is there benefit in running an initial simulation to calculate the height at which the ratio between vertical and horizontal velocity would be the best for being able to deply the chutes to control the landing site?

                // At what ASL height does the reference body have this pressure?
                //maxSemiDeployHeight = (this.body.atmosphereScaleHeight *1000) * -1 * Math.Log(minSemiDeployPressure / this.body.atmosphereMultiplier);
#warning FIX THAT BEFORE 1.0 !!
                maxSemiDeployHeight = (1 * 1000) * -1 * Math.Log(minSemiDeployPressure / 1);

                // We have to have semi deployed by the time we fully deploy.
                minSemiDeployHeight = maxFullDeployHeight;

                maxMultiplier = maxSemiDeployHeight / minSemiDeployHeight;

                // Set the inital mutiplier to be the mid point.
                currentMultiplier = maxMultiplier / 2;
            }
        }
Пример #8
0
 /// <summary>
 /// Keep track of the parachutes on the vessel.
 /// </summary>
 /// <param name="vessel"></param>
 private void UpdateVessel(Vessel vessel)
 {
     if ((vessel.persistentId == vesselId) && (vessel.parts.Count == vesselPartCount))
     {
         // nothing has changed, there's nothing to do
         return;
     }
     vesselId        = vessel.persistentId;
     vesselPartCount = vessel.parts.Count;
     parachutes.Clear();
     for (int i = 0; i < vessel.parts.Count; ++i)
     {
         ModuleParachute chute = AsParachute(vessel.parts[i]);
         if (chute != null)
         {
             parachutes.Add(chute);
         }
     }
 }
Пример #9
0
        private void AnalyzeParachutes()
        {
            parachuteDeployable = false;

            foreach (var pair in parachutes)
            {
                Part p = pair.Key;

                List <ModuleParachute> mlist = p.Modules.GetModules <ModuleParachute>();
                for (int i = 0; i < mlist.Count; i++)
                {
                    ModuleParachute chute = mlist[i];
                    if (chute.deploymentState != ModuleParachute.deploymentStates.DEPLOYED ||
                        chute.deploymentState != ModuleParachute.deploymentStates.SEMIDEPLOYED)
                    {
                        parachuteDeployable = true;
                    }
                }
            }
        }
Пример #10
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            Debug.Log("ModuleParachutePlus.Start(): v01.08");

            ParachuteModule = (ModuleParachute)GetModule("ModuleParachute");

            if (null == ParachuteModule)
            {
                Debug.LogWarning("ModuleParachuteFix.Start(): Did not find Parachute Module.");
                return;
            }

            canopy = part.FindModelTransform(ParachuteModule.canopyName);

            SetupStockPlus();
            GameEvents.onVesselWasModified.Add(CountSiblings);
            CountSiblings(vessel);
        }
Пример #11
0
 //Cuts the chute if it's deployed
 public override void FailPart()
 {
     chute = part.FindModuleImplementing <ModuleParachute>();
     if (chute == null)
     {
         return;
     }
     if (OhScrap.highlight)
     {
         OhScrap.SetFailedHighlight();
     }
     if (chute.vessel != FlightGlobals.ActiveVessel)
     {
         return;
     }
     if (chute.deploymentState == ModuleParachute.deploymentStates.SEMIDEPLOYED || chute.deploymentState == ModuleParachute.deploymentStates.DEPLOYED)
     {
         chute.CutParachute();
     }
 }
Пример #12
0
        public SimulatedParachute(ModuleParachute p)
        {
            this.p     = p;
            this.state = p.deploymentState;

            // Work out when the chute was put into its current state based on the current drag as compared to the stoed, semi deployed and fully deployed drag

            double timeSinceDeployment = 0;

            this.targetDrag    = p.targetDrag;
            this.parachuteDrag = p.parachuteDrag;

            switch (p.deploymentState)
            {
            case ModuleParachute.deploymentStates.SEMIDEPLOYED:
                // If the parachute is semi deployed calculate when it was semideployed by comparing the actual drag with the stowed drag and the semideployed drag.
                timeSinceDeployment = (p.parachuteDrag - p.stowedDrag) / (p.semiDeployedDrag - p.stowedDrag) * p.semiDeploymentSpeed;     // TODO there is an error in this, because the (semi)deployment does not increase the drag in a linear way. However this will only cause a problem for simulations run during the deployment and in unlikely to cause an error in the landing location.
                break;

            case ModuleParachute.deploymentStates.DEPLOYED:
                // If the parachute is deployed calculate when it was deployed by comparing the actual drag with the semideployed drag and the deployed drag.
                timeSinceDeployment = (p.parachuteDrag - p.semiDeployedDrag) / (p.fullyDeployedDrag - p.semiDeployedDrag) * p.deploymentSpeed;     // TODO there is an error in this, because the (semi)deployment does not increase the drag in a linear way. However this will only cause a problem for simulations run during the deployment and in unlikely to cause an error in the landing location.
                break;

            case ModuleParachute.deploymentStates.STOWED:
            case ModuleParachute.deploymentStates.ACTIVE:
                // If the parachute is stowed then for some reason p.parachuteDrag does not reflect the stowed drag. set this up by hand.
                this.parachuteDrag  = this.targetDrag = p.stowedDrag;
                timeSinceDeployment = 10000000;
                break;

            default:
                // otherwise set the time since deployment to be a very large number to indcate that it has been in that state for a long time (although we do not know how long!
                timeSinceDeployment = 10000000;
                break;
            }

            this.openningTime = -timeSinceDeployment;

            // Debug.Log("Parachute " + p.name + " parachuteDrag:" + p.parachuteDrag + " targetDrag:" + p.targetDrag + " stowedDrag:" + p.stowedDrag + " semiDeployedDrag:" + p.semiDeployedDrag + " fullyDeployedDrag:" + p.fullyDeployedDrag + " part.maximum_drag:" + p.part.maximum_drag + " part.minimum_drag:" + p.part.minimum_drag + " semiDeploymentSpeed:" + p.semiDeploymentSpeed + " deploymentSpeed:" + p.deploymentSpeed + " deploymentState:" + p.deploymentState + " timeSinceDeployment:" + timeSinceDeployment);
        }
        void DeployParachutes()
        {
            if (vesselState.mainBody.atmosphere && deployChutes)
            {
                for (int i = 0; i < vesselState.parachutes.Count; i++)
                {
                    ModuleParachute p = vesselState.parachutes[i];
                    // what is the ASL at which we should deploy this parachute? It is the actual deployment height above the surface + the ASL of the predicted landing point.
                    double LandingSiteASL = LandingAltitude;
                    double ParachuteDeployAboveGroundAtLandingSite = p.deployAltitude * this.parachutePlan.Multiplier;

                    double ASLDeployAltitude = ParachuteDeployAboveGroundAtLandingSite + LandingSiteASL;

                    if (p.part.inverseStage >= limitChutesStage && p.deploymentState == ModuleParachute.deploymentStates.STOWED &&
                        ASLDeployAltitude > vesselState.altitudeASL && p.deploymentSafeState == ModuleParachute.deploymentSafeStates.SAFE)
                    {
                        p.Deploy();
                        //Debug.Log("Deploying parachute " + p.name + " at " + ASLDeployAltitude + ". (" + LandingSiteASL + " + " + ParachuteDeployAboveGroundAtLandingSite +")");
                    }
                }
            }
        }
        // This methods works out if there are any parachutes that are capable of being deployed
        public bool ParachutesDeployable()
        {
            if (!vesselState.mainBody.atmosphere)
            {
                return(false);
            }
            if (!deployChutes)
            {
                return(false);
            }

            for (int i = 0; i < vesselState.parachutes.Count; i++)
            {
                ModuleParachute p = vesselState.parachutes[i];
                if (Math.Max(p.part.inverseStage, 0) >= limitChutesStage && p.deploymentState == ModuleParachute.deploymentStates.STOWED)
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #15
0
        public bool IsShielded(Vector3 direction)
        {
            if ((object)parachute != null)
            {
                ModuleParachute p = parachute;
                if (p.deploymentState == ModuleParachute.deploymentStates.DEPLOYED || p.deploymentState == ModuleParachute.deploymentStates.SEMIDEPLOYED)
                {
                    return(false);
                }
            }
            if ((object)realChute != null)
            {
                string mainDeployState = (string)rCType.GetField("depState").GetValue(realChute);
                string secDeployState  = (string)rCType.GetField("secDepState").GetValue(realChute);
                if ((mainDeployState + secDeployState).Contains("DEPLOYED")) // LOW, PRE, or just DEPLOYED
                {
                    return(false);
                }
            }

            if (GetShieldedStateFromFAR() == true)
            {
                return(true);
            }

            Ray ray = new Ray(part.transform.position + direction.normalized * adjustCollider, direction.normalized);

            RaycastHit[] hits = Physics.RaycastAll(ray, 10);
            foreach (RaycastHit hit in hits)
            {
                if (hit.rigidbody != null && hit.collider != part.collider)
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #16
0
        private void Init(Vessel v, ReentrySimulation.SimCurves _simCurves, double startTime, int limitChutesStage)
        {
            totalMass = 0;

            var oParts = v.Parts;

            count = oParts.Count;

            simCurves = _simCurves;

            if (parts.Capacity < count)
            {
                parts.Capacity = count;
            }

            for (int i = 0; i < count; i++)
            {
                SimulatedPart simulatedPart = null;
                bool          special       = false;
                for (int j = 0; j < oParts[i].Modules.Count; j++)
                {
                    ModuleParachute mp = oParts[i].Modules[j] as ModuleParachute;
                    if (mp != null && v.mainBody.atmosphere)
                    {
                        special       = true;
                        simulatedPart = SimulatedParachute.Borrow(mp, simCurves, startTime, limitChutesStage);
                    }
                }
                if (!special)
                {
                    simulatedPart = SimulatedPart.Borrow(oParts[i], simCurves);
                }

                parts.Add(simulatedPart);
                totalMass += simulatedPart.totalMass;
            }
        }
            public SimulatedVessel(Vessel v, SimCurves simCurves, double startTime, int limitChutesStage)
            {
                totalMass = 0;

                var oParts = v.Parts;

                count = oParts.Count;

                this.simCurves = simCurves;

                if (parts.Capacity < count)
                {
                    parts.Capacity = count;
                }

                for (int i = 0; i < count; i++)
                {
                    SimulatedPart simulatedPart = null;
                    bool          special       = false;
                    for (int j = 0; j < oParts[i].Modules.Count; j++)
                    {
                        ModuleParachute mp = oParts[i].Modules[j] as ModuleParachute;
                        if (mp != null && v.mainBody.atmosphere)
                        {
                            special       = true;
                            simulatedPart = new SimulatedParachute(mp, simCurves, startTime, limitChutesStage);
                        }
                    }
                    if (!special)
                    {
                        simulatedPart = new SimulatedPart(oParts[i], simCurves);
                    }

                    parts.Add(simulatedPart);
                    totalMass += simulatedPart.totalMass;
                }
            }
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            Debug.Log("ModuleParachutePlus.Start(): v01.10");

            ParachuteModule = (ModuleParachute)GetModule("ModuleParachute");

            if (null == ParachuteModule)
            {
                Debug.LogWarning("ModuleParachuteFix.Start(): Did not find Parachute Module.");
                return;
            }

            canopy = part.FindModelTransform(ParachuteModule.canopyName);

            SetupStockPlus();
            GameEvents.onVesselWasModified.Add(CountSiblings);
            CountSiblings(vessel);
        }
Пример #19
0
        private void OnWindow(int window_id)
        {
            try {
                GUILayout.BeginVertical();

                // Get all modules of the selected part:
                var                            part_title               = "";
                Part                           part                     = null;
                KRnDModule                     rnd_module               = null;
                List <ModuleEngines>           engine_modules           = null;
                ModuleRCS                      rcs_module               = null;
                ModuleReactionWheel            reaction_wheel_module    = null;
                ModuleDeployableSolarPanel     solar_panel_module       = null;
                ModuleWheelBase                landing_leg_module       = null;
                PartResource                   electric_charge_resource = null;
                ModuleGenerator                generator_module         = null;
                PartModule                     fission_generator        = null;
                List <ModuleResourceConverter> converter_modules        = null;
                ModuleParachute                parachute_module         = null;
                ModuleDataTransmitter          antenna_module           = null;
                ModuleScienceLab               science_lab              = null;
                List <PartResource>            fuel_resources           = null;
                ModuleResourceHarvester        harvester_module         = null;
                ModuleActiveRadiator           radiator_module          = null;
                ELConverter                    el_converter             = null;


                if (selectedPart != null)
                {
                    foreach (var a_part in PartLoader.LoadedPartsList)
                    {
                        if (a_part.partPrefab.name == selectedPart.name)
                        {
                            part       = a_part.partPrefab;
                            part_title = a_part.title;
                            break;
                        }
                    }

                    if (part)
                    {
                        antenna_module           = PartStats.GetModuleDataTransmitter(part);
                        science_lab              = PartStats.GetModuleScienceLab(part);
                        rnd_module               = PartStats.GetKRnDModule(part);
                        engine_modules           = PartStats.GetModuleEnginesList(part);
                        rcs_module               = PartStats.GetModuleRCS(part);
                        reaction_wheel_module    = PartStats.GetModuleReactionWheel(part);
                        solar_panel_module       = PartStats.GetModuleDeployableSolarPanel(part);
                        landing_leg_module       = PartStats.GetModuleWheelBase(part);
                        electric_charge_resource = PartStats.GetElectricCharge(part);
                        generator_module         = PartStats.GetModuleGenerator(part);
                        fission_generator        = PartStats.GetFissionGenerator(part);
                        converter_modules        = PartStats.GetModuleResourceConverterList(part);
                        parachute_module         = PartStats.GetModuleParachute(part);
                        fuel_resources           = PartStats.GetFuelResources(part);
                        harvester_module         = PartStats.GetModuleResourceHarvester(part);
                        radiator_module          = PartStats.GetModuleActiveRadiator(part);
                        el_converter             = PartStats.GetModuleElConverter(part);
                    }
                }

                if (!part)
                {
                    // No part selected:
                    GUILayout.BeginArea(new Rect(10, 5, _windowStyle.fixedWidth, 20));
                    GUILayout.Label("<b>Kerbal R&D: Select a part to improve</b>", _labelStyle);
                    GUILayout.EndArea();
                    GUILayout.EndVertical();
                    GUI.DragWindow();
                    return;
                }

                if (!rnd_module)
                {
                    // Invalid part selected:
                    GUILayout.BeginArea(new Rect(10, 5, _windowStyle.fixedWidth, 20));
                    GUILayout.Label("<b>Kerbal R&D: Select a different part to improve</b>", _labelStyle);
                    GUILayout.EndArea();
                    GUILayout.EndVertical();
                    GUI.DragWindow();
                    return;
                }

                // Get stats of the current version of the selected part:
                if (!KRnD.upgrades.TryGetValue(part.name, out var current_upgrade))
                {
                    current_upgrade = new PartUpgrades();
                }
                var current_info = BuildPartInfoString(part, current_upgrade);

                // Create a copy of the part-stats which we can use to mock an upgrade further below:
                var next_upgrade = current_upgrade.Clone();

                // Title:
                GUILayout.BeginArea(new Rect(10, 5, _windowStyle.fixedWidth, 20));
                var version = rnd_module.GetVersion();
                if (version != "")
                {
                    version = " - " + version;
                }
                GUILayout.Label("<b>" + part_title + version + "</b>", _labelStyle);
                GUILayout.EndArea();

                // List with upgrade-options:
                float options_width  = 100;
                var   options_height = _windowStyle.fixedHeight - 30 - 30 - 20;
                GUILayout.BeginArea(new Rect(10, 30 + 20, options_width, options_height));


                GUILayout.BeginVertical();

                var options = new List <string> {
                    "Dry Mass", "Max Temp"
                };
                if (engine_modules != null || rcs_module)
                {
                    options.Add("ISP Vac");
                    options.Add("ISP Atm");
                    options.Add("Fuel Flow");
                }

                if (antenna_module != null)
                {
                    options.Add("Antenna Power");
                }
                if (antenna_module != null && antenna_module.antennaType != AntennaType.INTERNAL)
                {
                    options.Add("Packet Size");
                }
                if (science_lab != null)
                {
                    options.Add("Data Storage");
                }

                if (reaction_wheel_module != null)
                {
                    options.Add("Torque");
                }
                if (solar_panel_module != null)
                {
                    options.Add("Charge Rate");
                }
                if (landing_leg_module != null)
                {
                    options.Add("Crash Tolerance");
                }
                if (electric_charge_resource != null)
                {
                    options.Add("Battery");
                }
                //if (fuel_resources != null) options.Add("Fuel Pressure");
                if (generator_module || fission_generator)
                {
                    options.Add("Generator");
                }
                if (converter_modules != null)
                {
                    options.Add("Converter");
                }
                if (parachute_module)
                {
                    options.Add("Parachute");
                }
                if (harvester_module)
                {
                    options.Add("Harvester");
                }
                if (radiator_module)
                {
                    options.Add("Radiator");
                }
                if (el_converter)
                {
                    options.Add("EL Converter");
                }

                if (_selectedUpgradeOption >= options.Count)
                {
                    _selectedUpgradeOption = 0;
                }
                _selectedUpgradeOption = GUILayout.SelectionGrid(_selectedUpgradeOption, options.ToArray(), 1, _buttonStyle);

                GUILayout.EndVertical();

                GUILayout.EndArea();

                var              selected_upgrade_option = options.ToArray()[_selectedUpgradeOption];
                int              current_upgrade_level;
                int              next_upgrade_level;
                int              science_cost;
                float            current_improvement_factor;
                float            next_improvement_factor;
                UpgradeConstants u_constants;

                if (!KRnD.originalStats.TryGetValue(part.name, out var original_stats))
                {
                    throw new Exception("no original-stats for part '" + part.name + "'");
                }

                //Func<PartUpgrades, int> improve_function;
                if (selected_upgrade_option == "ISP Vac")
                {
                    //improve_function = KRnD.ImproveIspVac;
                    current_upgrade_level      = current_upgrade.ispVac;
                    next_upgrade_level         = ++next_upgrade.ispVac;
                    u_constants                = ValueConstants.GetData(StringConstants.ISP_VAC);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.ispVac);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.ispVac);
                    science_cost               = u_constants.CalculateScienceCost(0, next_upgrade.ispVac);
                }
                else if (selected_upgrade_option == "ISP Atm")
                {
                    //improve_function = KRnD.ImproveIspAtm;
                    current_upgrade_level      = current_upgrade.ispAtm;
                    next_upgrade_level         = ++next_upgrade.ispAtm;
                    u_constants                = ValueConstants.GetData(StringConstants.ISP_ATM);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.ispAtm);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.ispAtm);
                    science_cost               = u_constants.CalculateScienceCost(0, next_upgrade.ispAtm);
                }
                else if (selected_upgrade_option == "Fuel Flow")
                {
                    //improve_function = KRnD.ImproveFuelFlow;
                    current_upgrade_level      = current_upgrade.fuelFlow;
                    next_upgrade_level         = ++next_upgrade.fuelFlow;
                    u_constants                = ValueConstants.GetData(StringConstants.FUEL_FLOW);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.fuelFlow);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.fuelFlow);
                    science_cost               = u_constants.CalculateScienceCost(0, next_upgrade.fuelFlow);
                }
                else if (selected_upgrade_option == "Dry Mass")
                {
                    //improve_function = KRnD.ImproveDryMass;
                    current_upgrade_level      = current_upgrade.dryMass;
                    next_upgrade_level         = ++next_upgrade.dryMass;
                    u_constants                = ValueConstants.GetData(StringConstants.DRY_MASS);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.dryMass);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.dryMass);
                    science_cost               = u_constants.CalculateScienceCost(original_stats.dryMass, next_upgrade.dryMass);
                }
                else if (selected_upgrade_option == "Torque")
                {
                    //improve_function = KRnD.ImproveTorque;
                    current_upgrade_level      = current_upgrade.torqueStrength;
                    next_upgrade_level         = ++next_upgrade.torqueStrength;
                    u_constants                = ValueConstants.GetData(StringConstants.TORQUE);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.torqueStrength);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.torqueStrength);
                    science_cost               = u_constants.CalculateScienceCost(original_stats.torqueStrength, next_upgrade.torqueStrength);
                }
                else if (selected_upgrade_option == "Antenna Power")
                {
                    //improve_function = KRnD.ImproveAntennaPower;
                    current_upgrade_level      = current_upgrade.antennaPower;
                    next_upgrade_level         = ++next_upgrade.antennaPower;
                    u_constants                = ValueConstants.GetData(StringConstants.ANTENNA_POWER);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.antennaPower);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.antennaPower);
                    science_cost               = u_constants.CalculateScienceCost((float)original_stats.antennaPower, next_upgrade.antennaPower);
                }
                else if (selected_upgrade_option == "Packet Size")
                {
                    //improve_function = KRnD.ImprovePacketSize;
                    current_upgrade_level      = current_upgrade.packetSize;
                    next_upgrade_level         = ++next_upgrade.packetSize;
                    u_constants                = ValueConstants.GetData(StringConstants.PACKET_SIZE);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.packetSize);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.packetSize);
                    science_cost               = u_constants.CalculateScienceCost(original_stats.packetSize, next_upgrade.packetSize);
                }
                else if (selected_upgrade_option == "Data Storage")
                {
                    //improve_function = KRnD.ImproveDataStorage;
                    current_upgrade_level      = current_upgrade.dataStorage;
                    next_upgrade_level         = ++next_upgrade.dataStorage;
                    u_constants                = ValueConstants.GetData(StringConstants.DATA_STORAGE);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.dataStorage);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.dataStorage);
                    science_cost               = u_constants.CalculateScienceCost(original_stats.dataStorage, next_upgrade.dataStorage);
                }
                else if (selected_upgrade_option == "Harvester")
                {
                    //improve_function = KRnD.ImproveResourceHarvester;
                    current_upgrade_level      = current_upgrade.resourceHarvester;
                    next_upgrade_level         = ++next_upgrade.resourceHarvester;
                    u_constants                = ValueConstants.GetData(StringConstants.RESOURCE_HARVESTER);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.resourceHarvester);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.resourceHarvester);
                    science_cost               = u_constants.CalculateScienceCost(original_stats.resourceHarvester, next_upgrade.resourceHarvester);
                }
                else if (selected_upgrade_option == "Radiator")
                {
                    //improve_function = KRnD.ImproveActiveRadiator;
                    current_upgrade_level      = current_upgrade.maxEnergyTransfer;
                    next_upgrade_level         = ++next_upgrade.maxEnergyTransfer;
                    u_constants                = ValueConstants.GetData(StringConstants.ENERGY_TRANSFER);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.maxEnergyTransfer);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.maxEnergyTransfer);
                    science_cost               = u_constants.CalculateScienceCost((float)original_stats.maxEnergyTransfer, next_upgrade.maxEnergyTransfer);
                }
                else if (selected_upgrade_option == "Charge Rate")
                {
                    //improve_function = KRnD.ImproveChargeRate;
                    current_upgrade_level      = current_upgrade.efficiencyMult;
                    next_upgrade_level         = ++next_upgrade.efficiencyMult;
                    u_constants                = ValueConstants.GetData(StringConstants.CHARGE_RATE);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.efficiencyMult);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.efficiencyMult);
                    science_cost               = u_constants.CalculateScienceCost(original_stats.efficiencyMult, next_upgrade.efficiencyMult);
                }
                else if (selected_upgrade_option == "Crash Tolerance")
                {
                    //improve_function = KRnD.ImproveCrashTolerance;
                    current_upgrade_level      = current_upgrade.crashTolerance;
                    next_upgrade_level         = ++next_upgrade.crashTolerance;
                    u_constants                = ValueConstants.GetData(StringConstants.CRASH_TOLERANCE);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.crashTolerance);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.crashTolerance);
                    science_cost               = u_constants.CalculateScienceCost(original_stats.crashTolerance, next_upgrade.crashTolerance);
                }
                else if (selected_upgrade_option == "Battery")
                {
                    //improve_function = KRnD.ImproveBatteryCharge;
                    current_upgrade_level      = current_upgrade.batteryCharge;
                    next_upgrade_level         = ++next_upgrade.batteryCharge;
                    u_constants                = ValueConstants.GetData(StringConstants.BATTERY_CHARGE);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.batteryCharge);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.batteryCharge);
                    science_cost               = u_constants.CalculateScienceCost((float)original_stats.batteryCharge, next_upgrade.batteryCharge);
                }
                else if (selected_upgrade_option == "Fuel Pressure")
                {
                    //improve_function = KRnD.ImproveFuelCapacity;
                    current_upgrade_level      = current_upgrade.fuelCapacity;
                    next_upgrade_level         = ++next_upgrade.fuelCapacity;
                    u_constants                = ValueConstants.GetData(StringConstants.FUEL_CAPACITY);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.fuelCapacity);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.fuelCapacity);
                    science_cost               = u_constants.CalculateScienceCost((float)original_stats.fuelCapacitiesSum, next_upgrade.fuelCapacity);
                }
                else if (selected_upgrade_option == "Generator")
                {
                    //improve_function = KRnD.ImproveGeneratorEfficiency;
                    current_upgrade_level      = current_upgrade.generatorEfficiency;
                    next_upgrade_level         = ++next_upgrade.generatorEfficiency;
                    u_constants                = ValueConstants.GetData(StringConstants.GENERATOR_EFFICIENCY);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.generatorEfficiency);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.generatorEfficiency);
                    science_cost               = u_constants.CalculateScienceCost(0, next_upgrade.generatorEfficiency);
                }
                else if (selected_upgrade_option == "Converter")
                {
                    //improve_function = KRnD.ImproveConverterEfficiency;
                    current_upgrade_level      = current_upgrade.converterEfficiency;
                    next_upgrade_level         = ++next_upgrade.converterEfficiency;
                    u_constants                = ValueConstants.GetData(StringConstants.CONVERTER_EFFICIENCY);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.converterEfficiency);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.converterEfficiency);
                    science_cost               = u_constants.CalculateScienceCost(0, next_upgrade.converterEfficiency);
                }
                else if (selected_upgrade_option == "Parachute")
                {
                    //improve_function = KRnD.ImproveParachuteStrength;
                    current_upgrade_level      = current_upgrade.parachuteStrength;
                    next_upgrade_level         = ++next_upgrade.parachuteStrength;
                    u_constants                = ValueConstants.GetData(StringConstants.PARACHUTE_STRENGTH);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.parachuteStrength);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.parachuteStrength);
                    science_cost               = u_constants.CalculateScienceCost((float)original_stats.chuteMaxTemp, next_upgrade.parachuteStrength);
                }
                else if (selected_upgrade_option == "Max Temp")
                {
                    //improve_function = KRnD.ImproveMaxTemperature;
                    current_upgrade_level      = current_upgrade.maxTemperature;
                    next_upgrade_level         = ++next_upgrade.maxTemperature;
                    u_constants                = ValueConstants.GetData(StringConstants.MAX_TEMPERATURE);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.maxTemperature);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.maxTemperature);
                    science_cost               = u_constants.CalculateScienceCost((float)original_stats.intMaxTemp, next_upgrade.maxTemperature);
                }
                else if (selected_upgrade_option == "EL Converter")
                {
                    //improve_function = KRnD.ImproveMaxTemperature;
                    current_upgrade_level      = current_upgrade.elConverter;
                    next_upgrade_level         = ++next_upgrade.elConverter;
                    u_constants                = ValueConstants.GetData(StringConstants.EL_CONVERTER);
                    current_improvement_factor = u_constants.CalculateImprovementFactor(current_upgrade.elConverter);
                    next_improvement_factor    = u_constants.CalculateImprovementFactor(next_upgrade.elConverter);
                    science_cost               = u_constants.CalculateScienceCost((float)original_stats.ELConverter, next_upgrade.elConverter);
                }
                else
                {
                    throw new Exception("unexpected option '" + selected_upgrade_option + "'");
                }

                var new_info = BuildPartInfoString(part, next_upgrade);                 // Calculate part-info if the selected stat was upgraded.
                new_info = HighlightChanges(current_info, new_info);

                // Current stats:
                GUILayout.BeginArea(new Rect(10 + options_width + 10, 30, _windowStyle.fixedWidth, 20));
                GUILayout.Label("<color=#FFFFFF><b>Current:</b> " + current_upgrade_level + " (" + current_improvement_factor.ToString("+0.##%;-0.##%;-") + ")</color>", _labelStyle);
                GUILayout.EndArea();

                var area_width  = (_windowStyle.fixedWidth - 20 - options_width) / 2;
                var area_height = options_height;
                GUILayout.BeginArea(new Rect(10 + options_width, 30 + 20, area_width, area_height));
                _scrollPos = GUILayout.BeginScrollView(_scrollPos, _scrollStyle, GUILayout.Width(area_width), GUILayout.Height(area_height));

                GUILayout.Label(current_info, _labelStyleSmall);
                GUILayout.EndScrollView();
                GUILayout.EndArea();

                // Next stats:
                GUILayout.BeginArea(new Rect(10 + options_width + area_width + 10, 30, _windowStyle.fixedWidth, 20));
                GUILayout.Label("<color=#FFFFFF><b>Next upgrade:</b> " + next_upgrade_level + " (" + next_improvement_factor.ToString("+0.##%;-0.##%;-") + ")</color>", _labelStyle);
                GUILayout.EndArea();

                GUILayout.BeginArea(new Rect(10 + options_width + area_width, 30 + 20, area_width, area_height));
                _scrollPos = GUILayout.BeginScrollView(_scrollPos, _scrollStyle, GUILayout.Width(area_width), GUILayout.Height(area_height));
                GUILayout.Label(new_info, _labelStyleSmall);
                GUILayout.EndScrollView();
                GUILayout.EndArea();

                // Bottom-line (display only if the upgrade would have an effect):
                if (Math.Abs(current_improvement_factor - next_improvement_factor) > float.Epsilon)
                {
                    GUILayout.BeginArea(new Rect(10, _windowStyle.fixedHeight - 25, _windowStyle.fixedWidth, 30));
                    float current_science = 0;
                    if (ResearchAndDevelopment.Instance != null)
                    {
                        current_science = ResearchAndDevelopment.Instance.Science;
                    }
                    var color = "FF0000";
                    if (current_science >= science_cost)
                    {
                        color = "00FF00";
                    }
                    GUILayout.Label("<b>Science: <color=#" + color + ">" + science_cost + " / " + Math.Floor(current_science) + "</color></b>", _labelStyle);
                    GUILayout.EndArea();
                    if (current_science >= science_cost && ResearchAndDevelopment.Instance != null && u_constants != null /*&& improve_function != null*/)
                    {
                        GUILayout.BeginArea(new Rect(_windowStyle.fixedWidth - 110, _windowStyle.fixedHeight - 30, 100, 30));
                        if (GUILayout.Button("Research", _buttonStyle))
                        {
                            //upgrade_function(part);
                            try {
                                if (!KRnD.upgrades.TryGetValue(part.name, out var store))
                                {
                                    store = new PartUpgrades();
                                    KRnD.upgrades.Add(part.name, store);
                                }

                                u_constants.upgradeFunction(store);
                                //improve_function(store);
                                KRnD.UpdateGlobalParts();
                                KRnD.UpdateEditorVessel();
                            } catch (Exception e) {
                                Debug.LogError("[KRnD] UpgradeIspVac(): " + e);
                            }



                            ResearchAndDevelopment.Instance.AddScience(-science_cost, TransactionReasons.RnDTechResearch);
                        }

                        GUILayout.EndArea();
                    }
                }

                GUILayout.EndVertical();
                GUI.DragWindow();
            } catch (Exception e) {
                Debug.LogError("[KRnD] GenerateWindow(): " + e);
            }
        }
 public override void OnLoad(ConfigNode node)
 {
     base.OnLoad(node);
     parachute = this.part.Modules.OfType <ModuleParachute>().Single();
 }
Пример #21
0
 public SimulatedParachute(ModuleParachute p)
 {
     this.p = p;
     state  = p.deploymentState;
 }
Пример #22
0
 public SimulatedParachute(ModuleParachute p)
 {
     this.p = p;
     state = p.deploymentState;
 }
Пример #23
0
 public override void OnAwake()
 {
     base.OnAwake();
     if (part && part.Modules != null) // thanks, FlowerChild!
     {
         is_engine = (part.Modules.Contains("ModuleEngines") || part.Modules.Contains("ModuleEnginesFX"));
         is_eva = part.Modules.Contains("KerbalEVA");
         if (part.Modules.Contains("ModuleParachute"))
             parachute = (ModuleParachute)part.Modules["ModuleParachute"];
         if (part.Modules.Contains("RealChuteModule"))
         {
             realChute = part.Modules["RealChuteModule"];
             rCType = realChute.GetType();
         }
     }
 }
Пример #24
0
 public void OnDestroy()
 {
     this.parachute      = null;
     this.EVARepairEvent = null;
 }
Пример #25
0
        public void Update()
        {
            Vessel vessel = FlightGlobals.ActiveVessel;             // easier to use vessel

            // safety check
            if (vessel == null || !HighLogic.LoadedSceneIsFlight)
            {
                return;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // atmospheric shake
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // up the shake based on atmopshereic density and surface speed
            float spdDensity = (float)(vessel.atmDensity) * (float)FlightGlobals.ship_srfSpeed;

            // limit here, mainly for space planes
            spdDensity = Mathf.Clamp(spdDensity, 0, maxSpdDensityEarly);

            // exagerate shake if semideployed, dampen if deployed
            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleParachute"))
                    {
                        ModuleParachute p = module as ModuleParachute;

                        if (p.deploymentState == ModuleParachute.deploymentStates.SEMIDEPLOYED && !vessel.LandedOrSplashed)
                        {
                            spdDensity *= 1.25f;
                        }

                        if (p.deploymentState == ModuleParachute.deploymentStates.DEPLOYED && !vessel.LandedOrSplashed)
                        {
                            spdDensity *= 0.75f;
                        }
                    }
                    // RealChute Support, reworked to be compatible with RealChute v1.2
                    if (module.moduleName.Contains("RealChuteModule"))
                    {
                        PartModule p          = part.Modules["RealChuteModule"];
                        Type       pType      = p.GetType();
                        object     parachutes = pType.GetField("parachutes").GetValue(p);
                        foreach (object parachute in (parachutes as IEnumerable))
                        {
                            Type cType = parachute.GetType();
                            if (cType.GetField("depState").GetValue(parachute) == "PREDEPLOYED")
                            {
                                spdDensity *= 1.25f;
                            }
                            if ((cType.GetField("depState").GetValue(parachute) == "DEPLOYED") || (cType.GetField("depState").GetValue(parachute) == "LOWDEPLOYED"))
                            {
                                spdDensity *= 0.75f;
                            }
                        }
                    }
                }
            }

            // lifted from DRE (thanks r4m0n), gets the mach / reentry fx
            if (afx == null)
            {
                GameObject fx = GameObject.Find("FXLogic");
                if (fx != null)
                {
                    afx = fx.GetComponent <AerodynamicsFX>();
                }
            }

            // sirhaxington special: use weird values I found to determine if mach or reentry, there has to be a better way...
            if ((afx != null) && (afx.FxScalar > 0.01))
            {
                // hack, whatever the .b color value is, always is this for re-entry, .11 something
                if (afx.fxLight.color.b < 0.12f)
                {
                    burnDownTime = atmoBurnDownTimes[0];
                }

                // hack, whatever the .b color value is, always is this for mach fx, .21 something
                if (afx.fxLight.color.b > 0.20f)
                {
                    // since we * 10, only do this if it's going to increase...
                    if (afx.FxScalar > 0.1)
                    {
                        spdDensity *= (afx.FxScalar * 10);
                    }
                }
            }

            // ease back into normal atmophere from re-entry
            if (burnDownTime > 0)
            {
                spdDensity   *= (afx.FxScalar * burnDownTime * 1000);
                burnDownTime -= Time.deltaTime;
            }

            // dont go too crazy...
            spdDensity = Mathf.Clamp(spdDensity, 0, maxSpdDensity);

            if (!vessel.isEVA)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * spdDensity) / 500000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, (UnityEngine.Random.Range(-0.1f, 0.1f) * spdDensity) / 5000), shakeRot);
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // parachute open shake
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            int chuteCheck = 0;                                 // re-do this every frame, check against previous frame to see if chute opened

            // a chute has popped...
            // Note: Don't need to do this with realChutes as they tend to open slow anyway
            foreach (Part part in vessel.parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleParachute"))
                    {
                        ModuleParachute p = module as ModuleParachute;

                        if (p.deploymentState != ModuleParachute.deploymentStates.DEPLOYED)
                        {
                            chuteCheck++;
                        }
                    }
                }
            }

            // check against previous frames' chutes, then prep shake event
            if (chuteCheck < totalUndeployedChutes)
            {
                doParaFull    = true;
                paraShakeTime = paraShakeTimes[0];
            }

            // set this at end of check for next frame
            totalUndeployedChutes = chuteCheck;

            // do the parachute pop shake
            if (paraShakeTime > 0 && doParaFull)
            {
                shakeAmt       = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 500, shakeAmt);
                shakeRot       = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.5f, 0.5f)), shakeRot);
                paraShakeTime -= Time.deltaTime;
            }
            else if (paraShakeTime <= 0)
            {
                doParaFull = false;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // decoupler shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // total is grabbed from event handler
            if (ejectionForceTotal > 0)
            {
                // playing around with set shake timers, not sure if I like this way but it works for now
                if (ejectionForceTotal <= 15)
                {
                    decoupleShakeTime = decoupleShakeTimes[0];
                }
                else if (ejectionForceTotal <= 250)
                {
                    decoupleShakeTime = decoupleShakeTimes[1];
                }
                else if (ejectionForceTotal <= 500)
                {
                    decoupleShakeTime = decoupleShakeTimes[2];
                }
                else if (ejectionForceTotal <= 1000)
                {
                    decoupleShakeTime = decoupleShakeTimes[3];
                }
                else
                {
                    decoupleShakeTime = decoupleShakeTimes[4];
                }

                decoupleShakeForce = ejectionForceTotal;

                doDecoupleShake    = true;
                ejectionForceTotal = 0;
            }

            // do the decoupler shake
            if (decoupleShakeTime > 0 && doDecoupleShake)
            {
                shakeAmt           = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere * decoupleShakeForce / 500000, shakeAmt);
                shakeRot           = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.5f, 0.5f)), shakeRot);
                decoupleShakeTime -= Time.deltaTime;
            }
            else if (decoupleShakeTime <= 0)
            {
                doDecoupleShake = false;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // docking shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // do the dock shake...we set the time from the handler, no need for other checks
            if (dockShakeTime > 0)
            {
                shakeAmt       = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 1000, shakeAmt);
                shakeRot       = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.07f, 0.07f)), shakeRot);
                dockShakeTime -= Time.deltaTime;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // launch clamp shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            int clampCheck = 0;

            // a clamp has detached...
            foreach (Part part in vessel.parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("LaunchClamp"))
                    {
                        LaunchClamp lc = module as LaunchClamp;

                        if (lc.enabled)
                        {
                            clampCheck++;
                        }
                    }
                }
            }

            // check against previous frames' chutes, then prep shake event
            if (clampCheck < totalClampedClamps)
            {
                doClamp        = true;
                clampShakeTime = clampShakeTimes[0];
            }

            // set this at end of check for next frame
            totalClampedClamps = clampCheck;

            // do the parachute pop shake
            if (clampShakeTime > 0 && doClamp)
            {
                shakeAmt        = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 500, shakeAmt);
                shakeRot        = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.7f, 0.7f)), shakeRot);
                clampShakeTime -= Time.deltaTime;
            }
            else if (clampShakeTime <= 0)
            {
                doClamp = false;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // engine shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // check both engine types (rapier uses ModuleEnginesFX, most use ModuleEngines) then base shake on thrust amount
            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleEnginesFX"))
                    {
                        ModuleEnginesFX e = module as ModuleEnginesFX;

                        if (e.isOperational)
                        {
                            float solidScalar = 1.0f;            // scale up SRBs

                            if (e.propellants.Count > 0)
                            {
                                foreach (Propellant p in e.propellants)
                                {
                                    if (p.name == "SolidFuel")
                                    {
                                        solidScalar = 2.5f;
                                    }
                                }
                            }
                            engineThrustTotal += (e.finalThrust * solidScalar);
                        }

                        if (engineThrustTotal > 0)
                        {
                            doEngineShake = true;
                        }
                    }
                    else if (module.moduleName.Contains("ModuleEngines"))
                    {
                        ModuleEngines e = module as ModuleEngines;

                        if (e.isOperational)
                        {
                            float typeScalar = 1.0f;            // scale up SRBs, down jets

                            if (e.propellants.Count > 0)
                            {
                                foreach (Propellant p in e.propellants)
                                {
                                    if (p.name == "SolidFuel")
                                    {
                                        typeScalar = 2.5f;
                                    }
                                    else if (p.name == "IntakeAir")
                                    {
                                        typeScalar = 0.01f;
                                    }
                                }
                            }
                            engineThrustTotal += (e.finalThrust * typeScalar);
                        }

                        if (engineThrustTotal > 0)
                        {
                            doEngineShake = true;
                        }
                    }

                    // don't go too crazy...
                    engineThrustTotal = Mathf.Clamp(engineThrustTotal, 0, maxEngineForce);
                }
            }

            // do engine shake...
            if (engineThrustTotal > 0 && doEngineShake)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * (engineThrustTotal / 1000)) / 800, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.8f, 0.8f) * (engineThrustTotal / 1000)), shakeRot);
            }
            else if (engineThrustTotal <= 0)
            {
                doEngineShake = false;
            }

            // reset every frame
            engineThrustTotal = 0;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // nearby collision shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // do the collision shake...we set the time from the handler, no need for other checks
            if (collisionShakeTime > 0)
            {
                shakeAmt            = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 50, shakeAmt);
                shakeRot            = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-1.5f, 1.5f)), shakeRot);
                collisionShakeTime -= Time.deltaTime;
            }

            // reset for next frame, use negative since we're looking for distance now
            collisionClosest = -1;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // rover ground shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            float spdRover = (float)FlightGlobals.ship_srfSpeed;

            doRover = false;
            float roverScalar = 1.0f;

            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleWheel"))
                    {
                        if (part.GroundContact)
                        {
                            if (vessel.landedAt.Length == 0 || vessel.landedAt.ToString() == "KSC")
                            {
                                roverScalar = 2.0f;
                            }
                            // maybe later, do biome specific shakes
                            //CBAttributeMap currentBiome = vessel.mainBody.BiomeMap;
                            //print(currentBiome.GetAtt(vessel.latitude * Mathf.Deg2Rad, vessel.longitude * Mathf.Deg2Rad).name);
                            //print(currentBiome.ToString());

                            doRover = true;
                        }
                    }
                    if (module.moduleName.Contains("ModuleLandingGear"))
                    {
                        if (part.Landed)
                        {
                            if (vessel.landedAt.Length == 0 || vessel.landedAt.ToString() == "KSC")         // basically, in and around KSC
                            {
                                roverScalar = 2.0f;
                            }

                            doRover = true;
                        }
                    }
                }
            }

            spdRover *= roverScalar;

            // dont go too crazy...
            spdRover = Mathf.Clamp(spdRover, 0, maxSpdRover);

            if (doRover && !vessel.isEVA)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * spdRover) / 50000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, (UnityEngine.Random.Range(-0.1f, 0.1f) * spdRover) / 500), shakeRot);
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // landing shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // note, parts that break off may throw this off
            int landedCurParts = 0;

            foreach (Part part in vessel.Parts)
            {
                if (part.GroundContact || part.WaterContact)
                {
                    landedCurParts++;
                }
            }

            // if more parts are touching the ground this frame...
            if (landedCurParts > landedPrevParts)
            {
                doLanded = true;

                // do I need horizontal surface speed as well? hmmm...
                landedShakeForce = landedPrevSrfSpd;

                if (landedShakeForce <= 0.5)
                {
                    landedShakeTime = landedShakeTimes[0];
                }
                else if (landedShakeForce <= 1.5)
                {
                    landedShakeTime = landedShakeTimes[1];
                }
                else if (landedShakeForce <= 3.0)
                {
                    landedShakeTime = landedShakeTimes[2];
                }
                else if (landedShakeForce <= 5.0)
                {
                    landedShakeTime = landedShakeTimes[3];
                }
                else
                {
                    landedShakeTime = landedShakeTimes[4];
                }

                if (doRover)
                {
                    landedShakeForce /= 2;
                }

                landedShakeForce = Mathf.Clamp(landedShakeForce, 0, maxLandedForce);
            }

            // set the current parts for the next frame
            landedPrevParts = landedCurParts;

            // do the landing / touching ground / water shake
            if (doLanded && !vessel.isEVA)
            {
                if (landedShakeTime > 0)
                {
                    shakeAmt         = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * landedShakeForce) / 3600, shakeAmt);
                    shakeRot         = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.1f, 0.1f) * landedShakeForce), shakeRot);
                    landedShakeTime -= Time.deltaTime;
                }
                else
                {
                    doLanded = false;
                }
            }

            // set the speed for the next frame
            landedPrevSrfSpd = (float)FlightGlobals.ActiveVessel.srfSpeed;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // EVA Shakes (under construction)
            //
            // to do: polish shakes (check on a few planets), rotation add back in
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            if (vessel.isEVA)
            {
                KerbalEVA eva = (KerbalEVA)vessel.rootPart.Modules["KerbalEVA"];

                // if an anim has changed
                if (eva.fsm.currentStateName != evaAnimState)
                {
                    //print(evaSrfSpedPrev);
                    if (eva.fsm.currentStateName == "Landing")                              // standard landing from a jump / RCS
                    {
                        evaShakeTime       = evaShakeTimes[2];
                        evaAnimShakeAmount = (int)(45000 / evaSrfSpedPrev);
                    }
                    else if (eva.fsm.currentStateName == "Ragdoll")                         // we landed too hard / jumped and landed at an odd angle
                    {
                        evaShakeTime       = evaShakeTimes[5];
                        evaAnimShakeAmount = (int)(8000 / evaSrfSpedPrev);
                    }
                    else if (eva.fsm.currentStateName == "Low G Bound (Grounded - FPS)")    // each step on a low g world should be felt
                    {
                        evaShakeTime       = evaShakeTimes[2];
                        evaAnimShakeAmount = (int)(50000);
                    }
                    else if (eva.fsm.currentStateName == "Ladder (Acquire)")                 // feel the grab a bit more
                    {
                        evaShakeTime       = evaShakeTimes[5];
                        evaAnimShakeAmount = (int)(1000000);
                    }
                    evaAnimState = eva.fsm.currentStateName;
                    //print(evaAnimState);
                }
                else if (evaAnimState == "Ragdoll" && vessel.Landed && evaShakeTime <= 0)    // when ragging and sliding along the surface, keep shaking
                {
                    evaShakeTime       = evaShakeTimes[5];
                    evaAnimShakeAmount = (int)(8000 / evaSrfSpedPrev);
                }
                else if (evaAnimState == "Ladder (Acquire)" && evaShakeTime >= 0)           // when ragging and sliding along the surface or falling, update shaking
                {
                    if (evaShakeTime < 0.3)
                    {
                        evaAnimShakeAmount = (int)(4000);
                    }
                }

                // update shake based on timers
                if (evaShakeTime > 0)
                {
                    shakeAmt      = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / evaAnimShakeAmount, shakeAmt);
                    evaShakeTime -= Time.deltaTime;
                }

                // RCS Cam Shake
                if (Math.Round(eva.Fuel, 3) != Math.Round(evaFuel, 3))
                {
                    evaFuel  = eva.Fuel;
                    shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / evaRCSShakeAmount, shakeAmt);
                    Math.Round(eva.Fuel, 3);
                }

                // grab frame two behind to test against
                evaSrfSpedPrev = evaSrfSped;
                evaSrfSped     = (float)vessel.srfSpeed;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // DO THE HARLEMSHAKE! o/\o
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // Set isCrewed to true if not unmanned, used to remove shake in control room when using ProbeControlRoom mod
            bool isCrewed = false;

            foreach (Part part in vessel.Parts)
            {
                if (part.protoModuleCrew.Count >= 1)
                {
                    isCrewed = true;
                }
            }

            // hopefully we've picked the largest values... also, don't shake while paused, looks dumb
            if (InternalCamera.Instance != null)
            {
                if (!gamePaused && InternalCamera.Instance.isActive && isCrewed) // isCrewed for shake only if not in control room
                {
                    InternalCamera.Instance.camera.transform.localPosition  = shakeAmt;
                    InternalCamera.Instance.camera.transform.localRotation *= shakeRot;
                }
            }


            // for a different first person EVA mod...
            bool FPEVAMod = false;

            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("EVACamera"))
                    {
                        FPEVAMod = true;
                    }
                }
            }

            // rotation is wonky in EVA, skip
            if (vessel.isEVA && FlightCamera.fetch.minDistance == 0.01f && FlightCamera.fetch.maxDistance == 0.01f)
            {
                if (shakeAmt.x != 0 && shakeAmt.y != 0 && shakeAmt.z != 0)
                {
                    FlightCamera.fetch.transform.localPosition += shakeAmt;
                }
            }
            else if (vessel.isEVA && FPEVAMod)
            {
                FlightCamera.fetch.transform.localPosition += (shakeAmt * 1000);
            }

            // reset the shake vals every frame and start over...
            shakeAmt = new Vector3(0.0f, 0.0f, 0.0f);
            shakeRot = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f);
        }
Пример #26
0
        public SimulatedParachute(ModuleParachute p)
        {
            this.p = p;
            this.state = p.deploymentState;

            // Work out when the chute was put into its current state based on the current drag as compared to the stoed, semi deployed and fully deployed drag

            double timeSinceDeployment = 0;
            this.targetDrag = p.targetDrag;
            this.parachuteDrag = p.parachuteDrag;

            switch (p.deploymentState)
            {
                case ModuleParachute.deploymentStates.SEMIDEPLOYED:
                    // If the parachute is semi deployed calculate when it was semideployed by comparing the actual drag with the stowed drag and the semideployed drag.
                    timeSinceDeployment = (p.parachuteDrag - p.stowedDrag) / (p.semiDeployedDrag - p.stowedDrag) * p.semiDeploymentSpeed; // TODO there is an error in this, because the (semi)deployment does not increase the drag in a linear way. However this will only cause a problem for simulations run during the deployment and in unlikely to cause an error in the landing location.
                    break;

                case ModuleParachute.deploymentStates.DEPLOYED:
                    // If the parachute is deployed calculate when it was deployed by comparing the actual drag with the semideployed drag and the deployed drag.
                    timeSinceDeployment = (p.parachuteDrag - p.semiDeployedDrag) / (p.fullyDeployedDrag - p.semiDeployedDrag) * p.deploymentSpeed; // TODO there is an error in this, because the (semi)deployment does not increase the drag in a linear way. However this will only cause a problem for simulations run during the deployment and in unlikely to cause an error in the landing location.
                    break;

                case ModuleParachute.deploymentStates.STOWED:
                case ModuleParachute.deploymentStates.ACTIVE:
                    // If the parachute is stowed then for some reason p.parachuteDrag does not reflect the stowed drag. set this up by hand.
                    this.parachuteDrag = this.targetDrag = p.stowedDrag;
                    timeSinceDeployment = 10000000;
                    break;

                default:
                    // otherwise set the time since deployment to be a very large number to indcate that it has been in that state for a long time (although we do not know how long!
                    timeSinceDeployment = 10000000;
                    break;
            }

            this.openningTime = -timeSinceDeployment;

            // Debug.Log("Parachute " + p.name + " parachuteDrag:" + p.parachuteDrag + " targetDrag:" + p.targetDrag + " stowedDrag:" + p.stowedDrag + " semiDeployedDrag:" + p.semiDeployedDrag + " fullyDeployedDrag:" + p.fullyDeployedDrag + " part.maximum_drag:" + p.part.maximum_drag + " part.minimum_drag:" + p.part.minimum_drag + " semiDeploymentSpeed:" + p.semiDeploymentSpeed + " deploymentSpeed:" + p.deploymentSpeed + " deploymentState:" + p.deploymentState + " timeSinceDeployment:" + timeSinceDeployment);
        }
Пример #27
0
        private void HandleVessel(Vessel vessel)
        {
            if (vessel == null)
            {
                return;
            }

            Debug.Log("Strategia: VesselValueImprover.HandleVessel");

            // Check for our trait
            bool needsIncrease = false;

            foreach (ProtoCrewMember pcm in VesselUtil.GetVesselCrew(vessel))
            {
                if (pcm.experienceTrait.Config.Name == trait)
                {
                    needsIncrease = true;
                    break;
                }
            }

            // Find all relevant parts
            foreach (Part p in vessel.parts)
            {
                foreach (PartModule m in p.Modules)
                {
                    switch (attribute)
                    {
                    case Attribute.ISP:
                        ModuleEngines engine = m as ModuleEngines;
                        if (engine != null)
                        {
                            FloatCurve curve = engine.atmosphereCurve;
                            ConfigNode node  = new ConfigNode();
                            curve.Save(node);

                            // Find and adjust the vacuum ISP
                            ConfigNode newNode = new ConfigNode();
                            foreach (ConfigNode.Value pair in node.values)
                            {
                                string[] values = pair.value.Split(new char[] { ' ' });
                                if (values[0] == "0")
                                {
                                    float value    = float.Parse(values[1]);
                                    float oldValue = value;
                                    SetValue(p.partInfo.name + "|" + engine.engineID, needsIncrease, ref value);
                                    values[1] = value.ToString("F1");
                                    newNode.AddValue(pair.name, string.Join(" ", values));
                                    Debug.Log("Setting ISP of " + p + " from " + oldValue + " to " + value);
                                }
                                else
                                {
                                    newNode.AddValue(pair.name, pair.value);
                                }
                            }
                            curve.Load(newNode);
                            engine.realIsp = curve.Evaluate(0);
                        }
                        break;

                    case Attribute.ParachuteDrag:
                        ModuleParachute parachute = m as ModuleParachute;
                        if (parachute != null)
                        {
                            SetValue(p.partName, needsIncrease, ref parachute.fullyDeployedDrag);
                        }
                        break;

                    case Attribute.StrutStrength:
                        CModuleStrut strut = m as CModuleStrut;
                        if (strut != null)
                        {
                            SetValue(p.partName + "_linear", needsIncrease, ref strut.linearStrength);
                            SetValue(p.partName + "_angular", needsIncrease, ref strut.angularStrength);
                        }
                        break;

                    case Attribute.ReactionWheelTorque:
                        ModuleReactionWheel reactionWheel = m as ModuleReactionWheel;
                        if (reactionWheel != null)
                        {
                            SetValue(p.partName + "_pitch", needsIncrease, ref reactionWheel.PitchTorque);
                            SetValue(p.partName + "_yaw", needsIncrease, ref reactionWheel.YawTorque);
                            SetValue(p.partName + "_roll", needsIncrease, ref reactionWheel.RollTorque);
                        }
                        break;
                    }
                }
            }
        }
 private void SetParachuteInfo()
 {
     moduleParachute = selectedPart.GetModule<ModuleParachute>();
     if (moduleParachute != null)
     {
         infoItems.Add(PartInfoItem.Create("Deployed Drag", Units.ConcatF(moduleParachute.semiDeployedDrag, moduleParachute.fullyDeployedDrag)));
         infoItems.Add(PartInfoItem.Create("Deployment Altitude", moduleParachute.deployAltitude.ToDistance()));
         infoItems.Add(PartInfoItem.Create("Deployment Pressure", moduleParachute.minAirPressureToOpen.ToString("F2")));
     }
 }
Пример #29
0
        public PartStats(Part part)
        {
            this.mass = part.mass;

            if (part.partInfo.variant != null)
            {
                kRnDVariants       = KRnD.getVariants(part);
                currentVariant     = part.partInfo.variant.Name;
                currentVariantMass = part.partInfo.variant.Mass;
                variantBaseMass    = part.baseVariant.Mass;
            }
            if (kRnDVariants != null)
            {
                hasVariants = true;
            }
            else
            {
                currentVariantMass = 0;
                variantBaseMass    = 0;
                hasVariants        = false;
            }
            this.skinMaxTemp = part.skinMaxTemp;
            this.intMaxTemp  = part.maxTemp;

            // There should only be one or the other, engines or RCS:
            List <ModuleEngines> engineModules = KRnD.getEngineModules(part);
            ModuleRCS            rcsModule     = KRnD.getRcsModule(part);

            if (engineModules != null)
            {
                this.maxFuelFlows     = new List <float>();
                this.atmosphereCurves = new List <FloatCurve>();

                for (int i = 0; i < engineModules.Count; i++)
                {
                    ModuleEngines engineModule = engineModules[i];

                    this.maxFuelFlows.Add(engineModule.maxFuelFlow);

                    FloatCurve atmosphereCurve = new FloatCurve();
                    for (int i5 = 0; i5 < engineModule.atmosphereCurve.Curve.length; i5++)
                    {
                        Keyframe frame = engineModule.atmosphereCurve.Curve[i5];
                        atmosphereCurve.Add(frame.time, frame.value);
                    }
                    this.atmosphereCurves.Add(atmosphereCurve);
                }
            }
            else if (rcsModule)
            {
                this.maxFuelFlows     = new List <float>();
                this.atmosphereCurves = new List <FloatCurve>();

                this.maxFuelFlows.Add(rcsModule.thrusterPower);
                FloatCurve atmosphereCurve = new FloatCurve();
                for (int i = 0; i < rcsModule.atmosphereCurve.Curve.length; i++)
                {
                    Keyframe frame = rcsModule.atmosphereCurve.Curve[i];
                    atmosphereCurve.Add(frame.time, frame.value);
                }
                this.atmosphereCurves.Add(atmosphereCurve);
            }

            ModuleReactionWheel reactionWheel = KRnD.getReactionWheelModule(part);

            if (reactionWheel)
            {
                this.torque = reactionWheel.RollTorque; // There is also pitch- and yaw-torque, but they should all be the same
            }

            // WIP
            //ModuleDataTransmitter dataTransmitter = KRnD.getDataTransmitterModule(part);
            //if (dataTransmitter)
            //{
            //    this.antPower = dataTransmitter.antennaPower;
            //}

            ModuleResourceHarvester resourceHarvester = KRnD.getResourceHarvesterModule(part);

            if (resourceHarvester)
            {
                this.harvester = resourceHarvester.Efficiency;
            }

            ModuleActiveRadiator activeRadiator = KRnD.getActiveRadiatorModule(part);

            if (activeRadiator)
            {
                this.radiatorEfficiency = activeRadiator.maxEnergyTransfer;
            }

            ModuleDeployableSolarPanel solarPanel = KRnD.getSolarPanelModule(part);

            if (solarPanel)
            {
                this.chargeRate = solarPanel.chargeRate;
            }

            ModuleWheelBase landingLeg = KRnD.getLandingLegModule(part);

            if (landingLeg)
            {
                this.crashTolerance = part.crashTolerance; // Every part has a crash tolerance, but we only want to improve landing legs.
            }

            PartResource electricCharge = KRnD.getChargeResource(part);

            if (electricCharge != null)
            {
                this.batteryCharge = electricCharge.maxAmount;
            }

            ModuleGenerator generator = KRnD.getGeneratorModule(part);

            if (generator != null)
            {
                generatorEfficiency = new Dictionary <String, double>();
                for (int i = 0; i < generator.resHandler.outputResources.Count; i++)
                {
                    ModuleResource outputResource = generator.resHandler.outputResources[i];

                    generatorEfficiency.Add(outputResource.name, outputResource.rate);
                }
            }

            PartModule fissionGenerator = KRnD.getFissionGeneratorModule(part);

            if (fissionGenerator != null)
            {
                fissionPowerGeneration = KRnD.getGenericModuleValue(fissionGenerator, "PowerGeneration");
            }

            // There might be different converter-modules in the same part with different names (eg for Fuel, Monopropellant, etc):
            List <ModuleResourceConverter> converterList = KRnD.getConverterModules(part);

            if (converterList != null)
            {
                converterEfficiency = new Dictionary <String, Dictionary <String, double> >();
                for (int i = 0; i < converterList.Count; i++)
                {
                    ModuleResourceConverter converter = converterList[i];

                    Dictionary <String, double> thisConverterEfficiency = new Dictionary <String, double>();
                    for (int i2 = 0; i2 < converter.outputList.Count; i2++)
                    {
                        ResourceRatio resourceRatio = converter.outputList[i2];

                        thisConverterEfficiency.Add(resourceRatio.ResourceName, resourceRatio.Ratio);
                    }
                    converterEfficiency.Add(converter.ConverterName, thisConverterEfficiency);
                }
            }

            ModuleParachute parachute = KRnD.getParachuteModule(part);

            if (parachute)
            {
                this.chuteMaxTemp = parachute.chuteMaxTemp;
            }

            ModuleProceduralFairing fairing = KRnD.getFairingModule(part);

            if (fairing)
            {
                this.fairingAreaMass = fairing.UnitAreaMass;
            }

            List <PartResource> fuelResources = KRnD.getFuelResources(part);

            if (fuelResources != null)
            {
                fuelCapacities    = new Dictionary <string, double>();
                fuelCapacitiesSum = 0;
                for (int i = 0; i < fuelResources.Count; i++)
                {
                    PartResource fuelResource = fuelResources[i];

                    fuelCapacities.Add(fuelResource.resourceName, fuelResource.maxAmount);
                    fuelCapacitiesSum += fuelResource.maxAmount;
                }
            }
        }
Пример #30
0
        // Returns the info-text of the given part with the given upgrades to be displayed in the GUI-comparison.
        private String getPartInfo(Part part, KRnDUpgrade upgradesToApply = null)
        {
            String      info             = "";
            KRnDUpgrade originalUpgrades = null;

            try
            {
                KRnDModule rndModule = KRnD.getKRnDModule(part);
                if (rndModule == null || (originalUpgrades = rndModule.getCurrentUpgrades()) == null)
                {
                    return(info);
                }

                // Upgrade the part to get the correct info, we revert it back to its previous values in the finally block below:
                KRnD.updatePart(part, upgradesToApply);
                List <ModuleEngines>           engineModules          = KRnD.getEngineModules(part);
                ModuleRCS                      rcsModule              = KRnD.getRcsModule(part);
                ModuleReactionWheel            reactionWheelModule    = KRnD.getReactionWheelModule(part);
                ModuleDeployableSolarPanel     solarPanelModule       = KRnD.getSolarPanelModule(part);
                ModuleWheelBase                landingLegModule       = KRnD.getLandingLegModule(part);
                PartResource                   electricChargeResource = KRnD.getChargeResource(part);
                ModuleGenerator                generatorModule        = KRnD.getGeneratorModule(part);
                PartModule                     fissionGenerator       = KRnD.getFissionGeneratorModule(part);
                List <ModuleResourceConverter> converterModules       = KRnD.getConverterModules(part);
                ModuleParachute                parachuteModule        = KRnD.getParachuteModule(part);
                ModuleProceduralFairing        fairingModule          = KRnD.getFairingModule(part);
                List <PartResource>            fuelResources          = KRnD.getFuelResources(part);

                // Basic stats:
                info  = "<color=#FFFFFF><b>Dry Mass:</b> " + part.mass.ToString("0.#### t") + "\n";
                info += "<b>Max Temp.:</b> " + part.maxTemp.ToString("0.#") + "/" + part.skinMaxTemp.ToString("0.#") + " °K\n";
                if (landingLegModule != null)
                {
                    info += "<b>Crash Tolerance:</b> " + part.crashTolerance.ToString("0.#### m/s") + "\n";
                }
                if (electricChargeResource != null)
                {
                    info += "<b>Electric Charge:</b> " + electricChargeResource.maxAmount.ToString() + "\n";
                }

                // Fuels:
                if (fuelResources != null)
                {
                    foreach (PartResource fuelResource in fuelResources)
                    {
                        // Reformat resource-names like "ElectricCharge" to "Electric Charge":
                        String fuelName = fuelResource.resourceName.ToString();
                        fuelName = Regex.Replace(fuelName, @"([a-z])([A-Z])", "$1 $2");
                        info    += "<b>" + fuelName + ":</b> " + fuelResource.maxAmount.ToString() + "\n";
                    }
                }

                // Module stats:
                info += "\n";
                if (engineModules != null)
                {
                    foreach (ModuleEngines engineModule in engineModules)
                    {
                        info += "<color=#99FF00><b>Engine";
                        if (engineModules.Count > 1)
                        {
                            info += " (" + engineModule.engineID.ToString() + ")";
                        }
                        info += ":</b></color>\n" + engineModule.GetInfo();
                        if (engineModules.Count > 1)
                        {
                            info += "\n";
                        }
                    }
                }
                if (rcsModule)
                {
                    info += "<color=#99FF00><b>RCS:</b></color>\n" + rcsModule.GetInfo();
                }
                if (reactionWheelModule)
                {
                    info += "<color=#99FF00><b>Reaction Wheel:</b></color>\n" + reactionWheelModule.GetInfo();
                }
                if (solarPanelModule)
                {
                    info += "<color=#99FF00><b>Solar Panel:</b></color>\n" + KRnD.getSolarPanelInfo(solarPanelModule);
                }
                if (generatorModule)
                {
                    info += "<color=#99FF00><b>Generator:</b></color>\n" + generatorModule.GetInfo();
                }
                if (fissionGenerator)
                {
                    info += "<color=#99FF00><b>Fission-Generator:</b></color>\n" + fissionGenerator.GetInfo();
                }
                if (converterModules != null)
                {
                    foreach (ModuleResourceConverter converterModule in converterModules)
                    {
                        info += "<color=#99FF00><b>Converter " + converterModule.ConverterName + ":</b></color>\n" + converterModule.GetInfo() + "\n";
                    }
                }
                if (parachuteModule)
                {
                    info += "<color=#99FF00><b>Parachute:</b></color>\n" + parachuteModule.GetInfo();
                }
                if (fairingModule)
                {
                    info += "<color=#99FF00><b>Fairing:</b></color>\n" + fairingModule.GetInfo();
                }
                info += "</color>";
            }
            catch (Exception e)
            {
                Debug.LogError("[KRnDGUI] getPartInfo(): " + e.ToString());
            }
            finally
            {
                try
                {
                    if (originalUpgrades != null)
                    {
                        KRnD.updatePart(part, originalUpgrades);
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError("[KRnDGUI] getPartInfo() restore of part failed: " + e.ToString());
                }
            }
            return(info);
        }
        protected void StartSimulation(bool addParachuteError)
        {
            double altitudeOfPreviousPrediction         = 0;
            double parachuteMultiplierForThisSimulation = this.parachuteSemiDeployMultiplier;

            if (addParachuteError)
            {
                errorSimulationRunning = true;
                errorStopwatch.Start(); //starts a timer that times how long the simulation takes
            }
            else
            {
                simulationRunning = true;
                stopwatch.Start(); //starts a timer that times how long the simulation takes
            }

            Orbit patch = GetReenteringPatch() ?? orbit;

            // Work out a mass for the total ship, a DragMass for everything except the parachutes that will be used (including the stowed parachutes that will not be used) and list of parchutes that will be used.
            double totalMass = 0;
            double dragMassExcludingUsedParachutes = 0;
            List <SimulatedParachute> usableChutes = new List <SimulatedParachute>();

            foreach (Part p in vessel.parts)
            {
                if (p.IsPhysicallySignificant())
                {
                    bool   partIsParachute = false;
                    double partDrag        = 0;
                    double partMass        = p.TotalMass();

                    totalMass += partMass;

                    // Is this part a parachute?
                    foreach (PartModule pm in p.Modules)
                    {
                        if (!pm.isEnabled)
                        {
                            continue;
                        }

                        if (pm is ModuleParachute)
                        {
                            ModuleParachute chute = (ModuleParachute)pm;
                            partIsParachute = true;
                            // This is a parachute, but is it one that will be used in the landing / rentry simulation?
                            if (deployChutes && p.inverseStage >= limitChutesStage)
                            {
                                // This chute will be used in the simualtion. Add it to the list of useage parachutes.
                                usableChutes.Add(new SimulatedParachute(chute, patch.StartUT));
                            }
                            else
                            {
                                partDrag = p.maximum_drag;
                            }
                        }
                    }

                    if (false == partIsParachute)
                    {
                        // Part is not a parachute. Just use its drag value.
                        partDrag = p.maximum_drag;
                    }

                    dragMassExcludingUsedParachutes += partDrag * partMass;
                }
            }

            // Work out what the landing altitude was of the last prediction, and use that to pass into the next simulation
            if (null != this.result)
            {
                if (result.outcome == ReentrySimulation.Outcome.LANDED && null != result.body)
                {
                    altitudeOfPreviousPrediction = this.GetResult().endASL; // Note that we are caling GetResult here to force the it to calculate the endASL, if it has not already done this. It is not allowed to do this previously as we are only allowed to do it from this thread, not the reentry simulation thread.
                }
            }

            // Is this a simulation run with errors added? If so then add some error to the parachute multiple
            if (addParachuteError)
            {
                System.Random random = new System.Random();
                parachuteMultiplierForThisSimulation *= ((double)1 + ((double)(random.Next(1000000) - 500000) / (double)10000000));
            }

            ReentrySimulation sim = new ReentrySimulation(patch, patch.StartUT, dragMassExcludingUsedParachutes, usableChutes, totalMass, descentSpeedPolicy, decelEndAltitudeASL, vesselState.limitedMaxThrustAccel, parachuteMultiplierForThisSimulation, altitudeOfPreviousPrediction, addParachuteError, dt);

            //Run the simulation in a separate thread
            ThreadPool.QueueUserWorkItem(RunSimulation, sim);
        }
Пример #32
0
        private void OnWindow(int windowId)
        {
            try
            {
                GUILayout.BeginVertical();

                // Get all modules of the selected part:
                String                         partTitle              = "";
                Part                           part                   = null;
                KRnDModule                     rndModule              = null;
                List <ModuleEngines>           engineModules          = null;
                ModuleRCS                      rcsModule              = null;
                ModuleReactionWheel            reactionWheelModule    = null;
                ModuleDeployableSolarPanel     solarPanelModule       = null;
                ModuleWheelBase                landingLegModule       = null;
                PartResource                   electricChargeResource = null;
                ModuleGenerator                generatorModule        = null;
                PartModule                     fissionGenerator       = null;
                List <ModuleResourceConverter> converterModules       = null;
                ModuleParachute                parachuteModule        = null;
                List <PartResource>            fuelResources          = null;
                if (selectedPart != null)
                {
                    foreach (AvailablePart aPart in PartLoader.LoadedPartsList)
                    {
                        if (aPart.partPrefab.name == selectedPart.name)
                        {
                            part      = aPart.partPrefab;
                            partTitle = aPart.title;
                            break;
                        }
                    }
                    if (part)
                    {
                        rndModule              = KRnD.getKRnDModule(part);
                        engineModules          = KRnD.getEngineModules(part);
                        rcsModule              = KRnD.getRcsModule(part);
                        reactionWheelModule    = KRnD.getReactionWheelModule(part);
                        solarPanelModule       = KRnD.getSolarPanelModule(part);
                        landingLegModule       = KRnD.getLandingLegModule(part);
                        electricChargeResource = KRnD.getChargeResource(part);
                        generatorModule        = KRnD.getGeneratorModule(part);
                        fissionGenerator       = KRnD.getFissionGeneratorModule(part);
                        converterModules       = KRnD.getConverterModules(part);
                        parachuteModule        = KRnD.getParachuteModule(part);
                        fuelResources          = KRnD.getFuelResources(part);
                    }
                }
                if (!part)
                {
                    // No part selected:
                    GUILayout.BeginArea(new Rect(10, 5, windowStyle.fixedWidth, 20));
                    GUILayout.Label("<b>Kerbal R&D: Select a part to improve</b>", labelStyle);
                    GUILayout.EndArea();
                    GUILayout.EndVertical();
                    GUI.DragWindow();
                    return;
                }
                else if (!rndModule)
                {
                    // Invalid part selected:
                    GUILayout.BeginArea(new Rect(10, 5, windowStyle.fixedWidth, 20));
                    GUILayout.Label("<b>Kerbal R&D: Select a different part to improve</b>", labelStyle);
                    GUILayout.EndArea();
                    GUILayout.EndVertical();
                    GUI.DragWindow();
                    return;
                }

                // Get stats of the current version of the selected part:
                KRnDUpgrade currentUpgrade;
                if (!KRnD.upgrades.TryGetValue(part.name, out currentUpgrade))
                {
                    currentUpgrade = new KRnDUpgrade();
                }
                String currentInfo = getPartInfo(part, currentUpgrade);

                // Create a copy of the part-stats which we can use to mock an upgrade further below:
                KRnDUpgrade nextUpgrade = currentUpgrade.clone();

                // Title:
                GUILayout.BeginArea(new Rect(10, 5, windowStyle.fixedWidth, 20));
                String version = rndModule.getVersion();
                if (version != "")
                {
                    version = " - " + version;
                }
                GUILayout.Label("<b>" + partTitle + version + "</b>", labelStyle);
                GUILayout.EndArea();

                // List with upgrade-options:
                float optionsWidth  = 100;
                float optionsHeight = windowStyle.fixedHeight - 30 - 30 - 20;
                GUILayout.BeginArea(new Rect(10, 30 + 20, optionsWidth, optionsHeight));

                List <String> options = new List <String>();
                options.Add("Dry Mass");
                options.Add("Max Temp");
                if (engineModules != null || rcsModule)
                {
                    options.Add("ISP Vac");
                    options.Add("ISP Atm");
                    options.Add("Fuel Flow");
                }
                if (reactionWheelModule != null)
                {
                    options.Add("Torque");
                }
                if (solarPanelModule != null)
                {
                    options.Add("Charge Rate");
                }
                if (landingLegModule != null)
                {
                    options.Add("Crash Tolerance");
                }
                if (electricChargeResource != null)
                {
                    options.Add("Battery");
                }
                if (fuelResources != null)
                {
                    options.Add("Fuel Pressure");
                }
                if (generatorModule || fissionGenerator)
                {
                    options.Add("Generator");
                }
                if (converterModules != null)
                {
                    options.Add("Converter");
                }
                if (parachuteModule)
                {
                    options.Add("Parachute");
                }
                if (this.selectedUpgradeOption >= options.Count)
                {
                    this.selectedUpgradeOption = 0;
                }
                this.selectedUpgradeOption = GUILayout.SelectionGrid(this.selectedUpgradeOption, options.ToArray(), 1, buttonStyle);
                GUILayout.EndArea();

                String           selectedUpgradeOption = options.ToArray()[this.selectedUpgradeOption];
                int              currentUpgradeCount   = 0;
                int              nextUpgradeCount      = 0;
                int              scienceCost           = 0;
                float            currentImprovement    = 0;
                float            nextImprovement       = 0;
                Func <Part, int> upgradeFunction       = null;
                if (selectedUpgradeOption == "ISP Vac")
                {
                    upgradeFunction     = KRnDGUI.UpgradeIspVac;
                    currentUpgradeCount = currentUpgrade.ispVac;
                    nextUpgradeCount    = ++nextUpgrade.ispVac;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.ispVac_improvement, rndModule.ispVac_improvementScale, currentUpgrade.ispVac);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.ispVac_improvement, rndModule.ispVac_improvementScale, nextUpgrade.ispVac);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.ispVac_scienceCost, rndModule.ispVac_costScale, nextUpgrade.ispVac);
                }
                else if (selectedUpgradeOption == "ISP Atm")
                {
                    upgradeFunction     = KRnDGUI.UpgradeIspAtm;
                    currentUpgradeCount = currentUpgrade.ispAtm;
                    nextUpgradeCount    = ++nextUpgrade.ispAtm;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.ispAtm_improvement, rndModule.ispAtm_improvementScale, currentUpgrade.ispAtm);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.ispAtm_improvement, rndModule.ispAtm_improvementScale, nextUpgrade.ispAtm);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.ispAtm_scienceCost, rndModule.ispAtm_costScale, nextUpgrade.ispAtm);
                }
                else if (selectedUpgradeOption == "Fuel Flow")
                {
                    upgradeFunction     = KRnDGUI.UpgradeFuelFlow;
                    currentUpgradeCount = currentUpgrade.fuelFlow;
                    nextUpgradeCount    = ++nextUpgrade.fuelFlow;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.fuelFlow_improvement, rndModule.fuelFlow_improvementScale, currentUpgrade.fuelFlow);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.fuelFlow_improvement, rndModule.fuelFlow_improvementScale, nextUpgrade.fuelFlow);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.fuelFlow_scienceCost, rndModule.fuelFlow_costScale, nextUpgrade.fuelFlow);
                }
                else if (selectedUpgradeOption == "Dry Mass")
                {
                    upgradeFunction     = KRnDGUI.UpgradeDryMass;
                    currentUpgradeCount = currentUpgrade.dryMass;
                    nextUpgradeCount    = ++nextUpgrade.dryMass;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.dryMass_improvement, rndModule.dryMass_improvementScale, currentUpgrade.dryMass);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.dryMass_improvement, rndModule.dryMass_improvementScale, nextUpgrade.dryMass);

                    // Scale science cost with original mass:
                    PartStats originalStats;
                    if (!KRnD.originalStats.TryGetValue(part.name, out originalStats))
                    {
                        throw new Exception("no original-stats for part '" + part.name + "'");
                    }
                    float scaleReferenceFactor = 1;
                    if (rndModule.dryMass_costScaleReference > 0)
                    {
                        scaleReferenceFactor = originalStats.mass / rndModule.dryMass_costScaleReference;
                    }
                    int scaledCost = (int)Math.Round(rndModule.dryMass_scienceCost * scaleReferenceFactor);
                    if (scaledCost < 1)
                    {
                        scaledCost = 1;
                    }
                    scienceCost = KRnD.calculateScienceCost(scaledCost, rndModule.dryMass_costScale, nextUpgrade.dryMass);
                }
                else if (selectedUpgradeOption == "Torque")
                {
                    upgradeFunction     = KRnDGUI.UpgradeTorque;
                    currentUpgradeCount = currentUpgrade.torque;
                    nextUpgradeCount    = ++nextUpgrade.torque;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.torque_improvement, rndModule.torque_improvementScale, currentUpgrade.torque);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.torque_improvement, rndModule.torque_improvementScale, nextUpgrade.torque);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.torque_scienceCost, rndModule.torque_costScale, nextUpgrade.torque);
                }
                else if (selectedUpgradeOption == "Charge Rate")
                {
                    upgradeFunction     = KRnDGUI.UpgradeChargeRate;
                    currentUpgradeCount = currentUpgrade.chargeRate;
                    nextUpgradeCount    = ++nextUpgrade.chargeRate;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.chargeRate_improvement, rndModule.chargeRate_improvementScale, currentUpgrade.chargeRate);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.chargeRate_improvement, rndModule.chargeRate_improvementScale, nextUpgrade.chargeRate);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.chargeRate_scienceCost, rndModule.chargeRate_costScale, nextUpgrade.chargeRate);
                }
                else if (selectedUpgradeOption == "Crash Tolerance")
                {
                    upgradeFunction     = KRnDGUI.UpgradeCrashTolerance;
                    currentUpgradeCount = currentUpgrade.crashTolerance;
                    nextUpgradeCount    = ++nextUpgrade.crashTolerance;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.crashTolerance_improvement, rndModule.crashTolerance_improvementScale, currentUpgrade.crashTolerance);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.crashTolerance_improvement, rndModule.crashTolerance_improvementScale, nextUpgrade.crashTolerance);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.crashTolerance_scienceCost, rndModule.crashTolerance_costScale, nextUpgrade.crashTolerance);
                }
                else if (selectedUpgradeOption == "Battery")
                {
                    upgradeFunction     = KRnDGUI.UpgradeBatteryCharge;
                    currentUpgradeCount = currentUpgrade.batteryCharge;
                    nextUpgradeCount    = ++nextUpgrade.batteryCharge;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.batteryCharge_improvement, rndModule.batteryCharge_improvementScale, currentUpgrade.batteryCharge);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.batteryCharge_improvement, rndModule.batteryCharge_improvementScale, nextUpgrade.batteryCharge);

                    // Scale science cost with original battery charge:
                    PartStats originalStats;
                    if (!KRnD.originalStats.TryGetValue(part.name, out originalStats))
                    {
                        throw new Exception("no origional-stats for part '" + part.name + "'");
                    }
                    double scaleReferenceFactor = 1;
                    if (rndModule.batteryCharge_costScaleReference > 0)
                    {
                        scaleReferenceFactor = originalStats.batteryCharge / rndModule.batteryCharge_costScaleReference;
                    }
                    int scaledCost = (int)Math.Round(rndModule.batteryCharge_scienceCost * scaleReferenceFactor);
                    if (scaledCost < 1)
                    {
                        scaledCost = 1;
                    }
                    scienceCost = KRnD.calculateScienceCost(scaledCost, rndModule.batteryCharge_costScale, nextUpgrade.batteryCharge);
                }
                else if (selectedUpgradeOption == "Fuel Pressure")
                {
                    upgradeFunction     = KRnDGUI.UpgradeFuelCapacity;
                    currentUpgradeCount = currentUpgrade.fuelCapacity;
                    nextUpgradeCount    = ++nextUpgrade.fuelCapacity;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.fuelCapacity_improvement, rndModule.fuelCapacity_improvementScale, currentUpgrade.fuelCapacity);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.fuelCapacity_improvement, rndModule.fuelCapacity_improvementScale, nextUpgrade.fuelCapacity);

                    // Scale science cost with original fuel capacity:
                    PartStats originalStats;
                    if (!KRnD.originalStats.TryGetValue(part.name, out originalStats))
                    {
                        throw new Exception("no origional-stats for part '" + part.name + "'");
                    }
                    double scaleReferenceFactor = 1;
                    if (rndModule.fuelCapacity_costScaleReference > 0)
                    {
                        scaleReferenceFactor = originalStats.fuelCapacitiesSum / rndModule.fuelCapacity_costScaleReference;
                    }
                    int scaledCost = (int)Math.Round(rndModule.fuelCapacity_scienceCost * scaleReferenceFactor);
                    if (scaledCost < 1)
                    {
                        scaledCost = 1;
                    }
                    scienceCost = KRnD.calculateScienceCost(scaledCost, rndModule.fuelCapacity_costScale, nextUpgrade.fuelCapacity);
                }
                else if (selectedUpgradeOption == "Generator")
                {
                    upgradeFunction     = KRnDGUI.UpgradeGeneratorEfficiency;
                    currentUpgradeCount = currentUpgrade.generatorEfficiency;
                    nextUpgradeCount    = ++nextUpgrade.generatorEfficiency;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.generatorEfficiency_improvement, rndModule.generatorEfficiency_improvementScale, currentUpgrade.generatorEfficiency);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.generatorEfficiency_improvement, rndModule.generatorEfficiency_improvementScale, nextUpgrade.generatorEfficiency);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.generatorEfficiency_scienceCost, rndModule.generatorEfficiency_costScale, nextUpgrade.generatorEfficiency);
                }
                else if (selectedUpgradeOption == "Converter")
                {
                    upgradeFunction     = KRnDGUI.UpgradeConverterEfficiency;
                    currentUpgradeCount = currentUpgrade.converterEfficiency;
                    nextUpgradeCount    = ++nextUpgrade.converterEfficiency;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.converterEfficiency_improvement, rndModule.converterEfficiency_improvementScale, currentUpgrade.converterEfficiency);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.converterEfficiency_improvement, rndModule.converterEfficiency_improvementScale, nextUpgrade.converterEfficiency);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.converterEfficiency_scienceCost, rndModule.converterEfficiency_costScale, nextUpgrade.converterEfficiency);
                }
                else if (selectedUpgradeOption == "Parachute")
                {
                    upgradeFunction     = KRnDGUI.UpgradeParachuteStrength;
                    currentUpgradeCount = currentUpgrade.parachuteStrength;
                    nextUpgradeCount    = ++nextUpgrade.parachuteStrength;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.parachuteStrength_improvement, rndModule.parachuteStrength_improvementScale, currentUpgrade.parachuteStrength);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.parachuteStrength_improvement, rndModule.parachuteStrength_improvementScale, nextUpgrade.parachuteStrength);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.parachuteStrength_scienceCost, rndModule.parachuteStrength_costScale, nextUpgrade.parachuteStrength);
                }
                else if (selectedUpgradeOption == "Max Temp")
                {
                    upgradeFunction     = KRnDGUI.UpgradeMaxTemperature;
                    currentUpgradeCount = currentUpgrade.maxTemperature;
                    nextUpgradeCount    = ++nextUpgrade.maxTemperature;
                    currentImprovement  = KRnD.calculateImprovementFactor(rndModule.maxTemperature_improvement, rndModule.maxTemperature_improvementScale, currentUpgrade.maxTemperature);
                    nextImprovement     = KRnD.calculateImprovementFactor(rndModule.maxTemperature_improvement, rndModule.maxTemperature_improvementScale, nextUpgrade.maxTemperature);
                    scienceCost         = KRnD.calculateScienceCost(rndModule.maxTemperature_scienceCost, rndModule.maxTemperature_costScale, nextUpgrade.maxTemperature);
                }
                else
                {
                    throw new Exception("unexpected option '" + selectedUpgradeOption + "'");
                }
                String newInfo = getPartInfo(part, nextUpgrade); // Calculate part-info if the selected stat was upgraded.
                newInfo = highlightChanges(currentInfo, newInfo);

                // Current stats:
                GUILayout.BeginArea(new Rect(10 + optionsWidth + 10, 30, windowStyle.fixedWidth, 20));
                GUILayout.Label("<color=#FFFFFF><b>Current:</b> " + currentUpgradeCount.ToString() + " (" + currentImprovement.ToString("+0.##%;-0.##%;-") + ")</color>", labelStyle);
                GUILayout.EndArea();

                float areaWidth  = (windowStyle.fixedWidth - 20 - optionsWidth) / 2;
                float areaHeight = optionsHeight;
                GUILayout.BeginArea(new Rect(10 + optionsWidth, 30 + 20, areaWidth, areaHeight));
                scrollPos = GUILayout.BeginScrollView(scrollPos, scrollStyle, GUILayout.Width(areaWidth), GUILayout.Height(areaHeight));

                GUILayout.Label(currentInfo, labelStyleSmall);
                GUILayout.EndScrollView();
                GUILayout.EndArea();

                // Next stats:
                GUILayout.BeginArea(new Rect(10 + optionsWidth + areaWidth + 10, 30, windowStyle.fixedWidth, 20));
                GUILayout.Label("<color=#FFFFFF><b>Next upgrade:</b> " + nextUpgradeCount.ToString() + " (" + nextImprovement.ToString("+0.##%;-0.##%;-") + ")</color>", labelStyle);
                GUILayout.EndArea();

                GUILayout.BeginArea(new Rect(10 + optionsWidth + areaWidth, 30 + 20, areaWidth, areaHeight));
                scrollPos = GUILayout.BeginScrollView(scrollPos, scrollStyle, GUILayout.Width(areaWidth), GUILayout.Height(areaHeight));
                GUILayout.Label(newInfo, labelStyleSmall);
                GUILayout.EndScrollView();
                GUILayout.EndArea();

                // Bottom-line (display only if the upgrade would have an effect):
                if (currentImprovement != nextImprovement)
                {
                    GUILayout.BeginArea(new Rect(10, windowStyle.fixedHeight - 25, windowStyle.fixedWidth, 30));
                    float currentScience = 0;
                    if (ResearchAndDevelopment.Instance != null)
                    {
                        currentScience = ResearchAndDevelopment.Instance.Science;
                    }
                    String color = "FF0000";
                    if (currentScience >= scienceCost)
                    {
                        color = "00FF00";
                    }
                    GUILayout.Label("<b>Science: <color=#" + color + ">" + scienceCost.ToString() + " / " + Math.Floor(currentScience).ToString() + "</color></b>", labelStyle);
                    GUILayout.EndArea();
                    if (currentScience >= scienceCost && ResearchAndDevelopment.Instance != null && upgradeFunction != null)
                    {
                        GUILayout.BeginArea(new Rect(windowStyle.fixedWidth - 110, windowStyle.fixedHeight - 30, 100, 30));
                        if (GUILayout.Button("Research", buttonStyle))
                        {
                            upgradeFunction(part);
                            ResearchAndDevelopment.Instance.AddScience(-scienceCost, TransactionReasons.RnDTechResearch);
                        }
                        GUILayout.EndArea();
                    }
                }

                GUILayout.EndVertical();
                GUI.DragWindow();
            }
            catch (Exception e)
            {
                Debug.LogError("[KRnD] GenerateWindow(): " + e.ToString());
            }
        }
Пример #33
0
 //============================================================================================================================================
 public void EngageChute()
 {
     //FAR Compatibility =)
     if (assemblyFARUsed == true) {
         foreach (Part EnabledPart in EnabledPartList) {
             if (EnabledPart.Modules.Contains ("RealChuteFAR")) {
                 //FerramAerospaceResearch.RealChuteLite.RealChuteFAR RCF = new FerramAerospaceResearch.RealChuteLite.RealChuteFAR ();
                 //RCF = EnabledPart.FindModuleImplementing<FerramAerospaceResearch.RealChuteLite.RealChuteFAR> ();
                 ChuteFARModuleReference = EnabledPart.Modules ["RealChuteFAR"];
                 PropertyInfo ChuteFARModuleDeploymentState = ChuteFARModuleReference.GetType().GetProperty("deploymentState");
                 RoboBrakes_ParaEnabledCount++;
                 ChuteFARDeploymentString = ChuteFARModuleReference.Fields.GetValue ("depState").ToString ();
                 //Repack if Chute was already Cut
                 if ((ChuteFARDeploymentString == "CUT") && (IsLanded == false) && (RoboBrakes_CHUTEAUTO == true)) {
                     //Bypassing RealChutes Repacking Method so we don't have to EVA - Also we can't set 'canRepack' bool as it is read only :-/
                     ChuteFARModuleDeploymentState.SetValue(ChuteFARModuleReference, 1, null);
                     ChuteFARModuleReference.part.Effect ("rcrepack");
                     ChuteFARModuleReference.part.stackIcon.SetIconColor (XKCDColors.White);
                     ChuteFARModuleReference.part.DragCubes.SetCubeWeight ("PACKED", 1);
                     ChuteFARModuleReference.part.DragCubes.SetCubeWeight ("RCDEPLOYED", 0);
                     print ("ROBOBRAKES - RealChute " + EnabledPart.name + " was already Cut! Repacked Automatically!");
                 }
                 //Deploy Chute
                 if ((RoboBrakes_CHUTEREADY == true && RoboBrakes_CHUTEAUTO == true)) {
                     RoboBrakes_CHUTEREADY = false;
                     //Deploy Real Chute
                     ChuteFARModuleReference.SendMessage("ActivateRC");
                 }
                 //Repack Chute Automatically
                 if (ChuteFARDeploymentString == "DEPLOYED" | ChuteFARDeploymentString == "PREDEPLOYED") {
                     if (RoboBrakes_CUTCHUTE == true) {
                         RoboBrakes_CUTCHUTE = false;
                         //Cut Real Chute
                         ChuteFARModuleReference.SendMessage("Cut");
                         //Bypassing RealChutes Repacking Method so we don't have to EVA - Also we can't set 'canRepack' bool as it is read only :-/
                         ChuteFARModuleDeploymentState.SetValue(ChuteFARModuleReference, 1, null);
                         ChuteFARModuleReference.part.Effect ("rcrepack");
                         ChuteFARModuleReference.part.stackIcon.SetIconColor (XKCDColors.White);
                         ChuteFARModuleReference.part.DragCubes.SetCubeWeight ("PACKED", 1);
                         ChuteFARModuleReference.part.DragCubes.SetCubeWeight ("RCDEPLOYED", 0);
                         print ("ROBOBRAKES - RealChute " + EnabledPart.name + " was Cut & Repacked Automatically!");
                     }
                 }
             }
         }
     }
     foreach (Part EnabledPart in EnabledPartList) {
         //Module Parachutes
         //---------------------------------------------------------------------------------------------------------------------
         if (EnabledPart.Modules.Contains ("ModuleParachute")) {
             ModuleParachute MPA = new ModuleParachute ();
             MPA = EnabledPart.FindModuleImplementing<ModuleParachute> ();
             RoboBrakes_ParaEnabledCount++;
             //Repack the Chute automatically if it has been manually cut
             if ((MPA.deploymentState.Equals (ModuleParachute.deploymentStates.CUT)) && (IsLanded == false) && (RoboBrakes_CHUTEAUTO == true)) {
                 MPA.Repack ();
                 print ("ROBOBRAKES - Chute " + EnabledPart.name + " was already Cut! Repacked Automatically!");
             }
             //Deploy Chute
             if ((RoboBrakes_AUTOMATICBRAKE_ACTIVE == true && RoboBrakes_CHUTEAUTO == true)) {
                 if (RoboBrakes_CHUTEREADY == true) {
                     RoboBrakes_CHUTEREADY = false;
                     MPA.Deploy ();
                 }
             }
             //Repack Chute
             if (MPA.deploymentState.Equals (ModuleParachute.deploymentStates.DEPLOYED)) {
                 if (RoboBrakes_CUTCHUTE == true) {
                     RoboBrakes_CUTCHUTE = false;
                     MPA.CutParachute ();
                     MPA.Repack ();
                     print ("ROBOBRAKES - Chute " + EnabledPart.name + " was Cut & Repacked Automatically!");
                 }
             }
         }
     }
 }
Пример #34
0
 public Parachute(VesselWrapper VSL, ModuleParachute p) : base(VSL)
 {
     parachute = p;
 }
Пример #35
0
        public void vesselDestroyEvent(Vessel v)
        {
            if (!KCT_GameStates.settings.enabledForSave)
            {
                return;
            }
            Dictionary <string, int> PartsRecovered = new Dictionary <string, int>();
            float         FundsRecovered = 0, KSCDistance = 0, RecoveryPercent = 0;
            StringBuilder Message = new StringBuilder();

            if (FlightGlobals.fetch == null)
            {
                return;
            }

            if (v != null && !(HighLogic.LoadedSceneIsFlight && v.isActiveVessel) && v.mainBody.bodyName == "Kerbin" && (!v.loaded || v.packed) && v.altitude < 35000 &&
                (v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.SUB_ORBITAL) && !v.isEVA)
            {
                double totalMass      = 0;
                double dragCoeff      = 0;
                bool   realChuteInUse = false;

                float RCParameter = 0;

                if (!v.packed) //adopted from mission controller.
                {
                    foreach (Part p in v.Parts)
                    {
                        p.Pack();
                    }
                }

                if (v.protoVessel == null)
                {
                    return;
                }
                KCTDebug.Log("Attempting to recover vessel.");
                try
                {
                    foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots)
                    {
                        //KCTDebug.Log("Has part " + p.partName + ", mass " + p.mass);
                        List <string> ModuleNames = new List <string>();
                        foreach (ProtoPartModuleSnapshot ppms in p.modules)
                        {
                            //Debug.Log(ppms.moduleName);
                            ModuleNames.Add(ppms.moduleName);
                        }
                        totalMass += p.mass;
                        totalMass += GetResourceMass(p.resources);
                        bool isParachute = false;
                        if (ModuleNames.Contains("ModuleParachute"))
                        {
                            KCTDebug.Log("Found parachute module on " + p.partInfo.name);
                            //Find the ModuleParachute (find it in the module list by checking for a module with the name ModuleParachute)
                            ProtoPartModuleSnapshot ppms = p.modules.First(mod => mod.moduleName == "ModuleParachute");
                            float drag = 500;
                            if (ppms.moduleRef != null)
                            {
                                ModuleParachute mp = (ModuleParachute)ppms.moduleRef;
                                mp.Load(ppms.moduleValues);
                                drag = mp.fullyDeployedDrag;
                            }
                            //Add the part mass times the fully deployed drag (typically 500) to the dragCoeff variable (you'll see why later)
                            dragCoeff += p.mass * drag;
                            //This is most definitely a parachute part
                            isParachute = true;
                        }
                        if (ModuleNames.Contains("RealChuteModule"))
                        {
                            KCTDebug.Log("Found realchute module on " + p.partInfo.name);
                            ProtoPartModuleSnapshot realChute = p.modules.First(mod => mod.moduleName == "RealChuteModule");
                            if ((object)realChute != null) //Some of this was adopted from DebRefund, as Vendan's method of handling multiple parachutes is better than what I had.
                            {
                                Type matLibraryType = AssemblyLoader.loadedAssemblies
                                                      .SelectMany(a => a.assembly.GetExportedTypes())
                                                      .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialsLibrary");

                                ConfigNode[] parchutes = realChute.moduleValues.GetNodes("PARACHUTE");
                                foreach (ConfigNode chute in parchutes)
                                {
                                    float  diameter = float.Parse(chute.GetValue("deployedDiameter"));
                                    string mat      = chute.GetValue("material");
                                    System.Reflection.MethodInfo matMethod = matLibraryType.GetMethod("GetMaterial", new Type[] { mat.GetType() });
                                    object MatLibraryInstance = matLibraryType.GetProperty("instance").GetValue(null, null);
                                    object materialObject     = matMethod.Invoke(MatLibraryInstance, new object[] { mat });
                                    float  dragC = (float)KCT_Utilities.GetMemberInfoValue(materialObject.GetType().GetMember("dragCoefficient")[0], materialObject);

                                    RCParameter += dragC * (float)Math.Pow(diameter, 2);
                                }
                                isParachute    = true;
                                realChuteInUse = true;
                            }
                        }
                        if (!isParachute)
                        {
                            if (p.partRef != null)
                            {
                                dragCoeff += p.mass * p.partRef.maximum_drag;
                            }
                            else
                            {
                                dragCoeff += p.mass * 0.2;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError("[KCT] Error while attempting to recover vessel.");
                    Debug.LogException(e);
                }
                double Vt = double.MaxValue;
                if (!realChuteInUse)
                {
                    dragCoeff = dragCoeff / (totalMass);
                    Vt        = Math.Sqrt((250 * 6.674E-11 * 5.2915793E22) / (3.6E11 * 1.22309485 * dragCoeff));
                    KCTDebug.Log("Using Stock Module! Drag: " + dragCoeff + " Vt: " + Vt);
                }
                else
                {
                    Vt = Math.Sqrt((8000 * totalMass * 9.8) / (1.223 * Math.PI) * Math.Pow(RCParameter, -1)); //This should work perfect for multiple identical chutes and gives an approximation for multiple differing chutes
                    KCTDebug.Log("Using RealChute Module! Vt: " + Vt);
                }
                if (Vt < 10.0)
                {
                    KCTDebug.Log("Recovered parts from " + v.vesselName);
                    foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots)
                    {
                        KCT_Utilities.AddPartToInventory(p.partInfo.name + KCT_Utilities.GetTweakScaleSize(p));
                        if (!PartsRecovered.ContainsKey(p.partInfo.title))
                        {
                            PartsRecovered.Add(p.partInfo.title, 1);
                        }
                        else
                        {
                            ++PartsRecovered[p.partInfo.title];
                        }
                    }

                    Message.AppendLine("Vessel name: " + v.vesselName);
                    Message.AppendLine("Parts recovered: ");
                    for (int i = 0; i < PartsRecovered.Count; i++)
                    {
                        Message.AppendLine(PartsRecovered.Values.ElementAt(i) + "x " + PartsRecovered.Keys.ElementAt(i));
                    }

                    if (KCT_Utilities.CurrentGameIsCareer())
                    {
                        if (KCT_Utilities.StageRecoveryAddonActive || KCT_Utilities.DebRefundAddonActive) //Delegate funds handling to Stage Recovery or DebRefund if it's present
                        {
                            KCTDebug.Log("Delegating Funds recovery to another addon.");
                        }
                        else  //Otherwise do it ourselves
                        {
                            bool probeCoreAttached = false;
                            foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots)
                            {
                                if (pps.modules.Find(module => (module.moduleName == "ModuleCommand" && ((ModuleCommand)module.moduleRef).minimumCrew == 0)) != null)
                                {
                                    KCTDebug.Log("Probe Core found!");
                                    probeCoreAttached = true;
                                    break;
                                }
                            }
                            float RecoveryMod = probeCoreAttached ? 1.0f : KCT_GameStates.settings.RecoveryModifier;
                            KSCDistance = (float)SpaceCenter.Instance.GreatCircleDistance(SpaceCenter.Instance.cb.GetRelSurfaceNVector(v.protoVessel.latitude, v.protoVessel.longitude));
                            double maxDist = SpaceCenter.Instance.cb.Radius * Math.PI;
                            RecoveryPercent = RecoveryMod * Mathf.Lerp(0.98f, 0.1f, (float)(KSCDistance / maxDist));
                            float totalReturn = 0;
                            foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots)
                            {
                                float dryCost, fuelCost;
                                totalReturn += Math.Max(ShipConstruction.GetPartCosts(pps, pps.partInfo, out dryCost, out fuelCost), 0);
                            }
                            float totalBeforeModifier = totalReturn;
                            totalReturn   *= RecoveryPercent;
                            FundsRecovered = totalReturn;
                            KCTDebug.Log("Vessel being recovered by KCT. Percent returned: " + 100 * RecoveryPercent + "%. Distance from KSC: " + Math.Round(KSCDistance / 1000, 2) + " km");
                            KCTDebug.Log("Funds being returned: " + Math.Round(totalReturn, 2) + "/" + Math.Round(totalBeforeModifier, 2));

                            Message.AppendLine("Funds recovered: " + FundsRecovered + "(" + Math.Round(RecoveryPercent * 100, 1) + "%)");
                            KCT_Utilities.AddFunds(FundsRecovered);
                        }
                    }
                    Message.AppendLine("\nAdditional information:");
                    Message.AppendLine("Distance from KSC: " + Math.Round(KSCDistance / 1000, 2) + " km");
                    if (!realChuteInUse)
                    {
                        Message.AppendLine("Stock module used. Terminal velocity (less than 10 needed): " + Math.Round(Vt, 2));
                    }
                    else
                    {
                        Message.AppendLine("RealChute module used. Terminal velocity (less than 10 needed): " + Math.Round(Vt, 2));
                    }
                    if (!(KCT_Utilities.StageRecoveryAddonActive || KCT_Utilities.DebRefundAddonActive) &&
                        (KCT_Utilities.CurrentGameIsCareer() || !KCT_GUI.PrimarilyDisabled) &&
                        !(KCT_GameStates.settings.DisableAllMessages || KCT_GameStates.settings.DisableRecoveryMessages))
                    {
                        KCT_Utilities.DisplayMessage("Stage Recovered", Message, MessageSystemButton.MessageButtonColor.BLUE, MessageSystemButton.ButtonIcons.MESSAGE);
                    }
                }
            }
        }
Пример #36
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            parachute = this.part.FindModuleImplementing <ModuleParachute>();
        }
Пример #37
0
        /// <summary>
        /// We check if the vessel was crashing. If so, we set the crashed flag
        /// </summary>
        /// <param name="v">V.</param>
        private void onVesselDestroy(Vessel v)
        {
            // If it has been destroyed under 10 meters above surface, it probably crashed
            if (v.mainBody.GetAltitude(v.CoM) - (v.terrainAltitude < 0 ? 0 : v.terrainAltitude) < 10)
            {
                eventFlags = eventFlags.Add(EventFlags.CRASHED);
            }
            // NK recycle
            else
            {
                try { print("*MC* Vessel " + v.name + " destroyed. Alt " + v.mainBody.GetAltitude(v.CoM) + ", body " + v.orbit.referenceBody.bodyName + ", sit = " + v.situation); }
                catch { }
                if (!HighLogic.LoadedSceneIsEditor && canRecycle && activeVessel != v && !v.isEVA && // canRecycle is false iff load requested and haven't returned to flight yet.
                    v.name.Contains("(Unloaded)") && // check make sure it's because we're unloading it
                    (v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.SUB_ORBITAL) && v.mainBody.GetAltitude(v.CoM) <= 25000 && v.orbit.referenceBody.bodyName.Equals("Kerbin") &&
                    settings.difficulty != 0)
                {
                    print("*MC* Checking " + v.name);
                    double mass  = 0;
                    double pdrag = 0.0;
                    int    cost  = 0;
                    double AUTORECYCLE_COST_MULT = 0.6;
                    // need 70 drag per ton of vessel for 6m/s at 500m.
                    const double PARACHUTE_DRAG_PER_TON = 70.0;
                    try
                    {
                        foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots)
                        {
                            print("Has part " + p.partName + ", mass " + p.mass + ", cost " + p.partRef.partInfo.cost);
                            mass += p.mass;
                            cost += p.partRef.partInfo.cost;
                            foreach (ProtoPartModuleSnapshot m in p.modules)
                            {
                                if (m.moduleName.Equals("ModuleParachute"))
                                {
                                    ModuleParachute mp = (ModuleParachute)m.moduleRef;
                                    pdrag += p.mass * mp.fullyDeployedDrag;
                                    print("Drag now " + pdrag);
                                }
                            }
                        }
                        if (mass * PARACHUTE_DRAG_PER_TON <= pdrag)
                        {
                            recycledName = v.name;
                            recycledCost = (int)((double)cost * AUTORECYCLE_COST_MULT);
                            print("*MC* Recycling vessel: enough parachutes! Val: " + cost + " * " + AUTORECYCLE_COST_MULT + " = " + recycledCost);
                            showRecycleWindow = true;
                            manager.recycleVessel(v, recycledCost);
                        }
                    }
                    catch { }
                }
            }

            // We should remove the onflybywire listener, if there is one
            try
            {
                v.OnFlyByWire -= this.onFlyByWire;
            }
            catch { }
        }
Пример #38
0
        public void BreakShipIntoStages()
        {
            stages.Clear();
            //loop through the part tree and try to break it into stages
            List <Part>    parts          = EditorLogic.fetch.ship.parts;
            EditorStatItem current        = new EditorStatItem();
            int            stageNum       = 0;
            bool           realChuteInUse = false;

            StageParts  stage = new StageParts();
            List <Part> RemainingDecouplers = new List <Part>()
            {
                parts[0]
            };

            while (RemainingDecouplers.Count > 0)
            {
                //determine stages from the decouplers
                Part parent = RemainingDecouplers[0];
                RemainingDecouplers.RemoveAt(0);
                stage               = DetermineStage(parent);
                current             = new EditorStatItem();
                current.stageNumber = stageNum++;
                current.parts       = stage.parts;
                RemainingDecouplers.AddRange(stage.decouplers);

                //compute properties
                foreach (Part part in stage.parts)
                {
                    current.dryMass += part.mass;
                    current.mass    += part.mass + part.GetResourceMass();

                    double pChutes = 0;
                    if (part.Modules.Contains("RealChuteModule"))
                    {
                        PartModule realChute = part.Modules["RealChuteModule"];
                        ConfigNode rcNode    = new ConfigNode();
                        realChute.Save(rcNode);

                        //This is where the Reflection starts. We need to access the material library that RealChute has, so we first grab it's Type
                        Type matLibraryType = AssemblyLoader.loadedAssemblies
                                              .SelectMany(a => a.assembly.GetExportedTypes())
                                              .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialsLibrary.MaterialsLibrary");


                        //We make a list of ConfigNodes containing the parachutes (usually 1, but now there can be any number of them)
                        //We get that from the PPMS
                        ConfigNode[] parachutes = rcNode.GetNodes("PARACHUTE");
                        //We then act on each individual parachute in the module
                        foreach (ConfigNode chute in parachutes)
                        {
                            //First off, the diameter of the parachute. From that we can (later) determine the Vt, assuming a circular chute
                            float diameter = float.Parse(chute.GetValue("deployedDiameter"));
                            //The name of the material the chute is made of. We need this to get the actual material object and then the drag coefficient
                            string mat = chute.GetValue("material");
                            //This grabs the method that RealChute uses to get the material. We will invoke that with the name of the material from before.
                            System.Reflection.MethodInfo matMethod = matLibraryType.GetMethod("GetMaterial", new Type[] { mat.GetType() });
                            //In order to invoke the method, we need to grab the active instance of the material library
                            object MatLibraryInstance = matLibraryType.GetProperty("Instance").GetValue(null, null);
                            //With the library instance we can invoke the GetMaterial method (passing the name of the material as a parameter) to receive an object that is the material
                            object materialObject = matMethod.Invoke(MatLibraryInstance, new object[] { mat });
                            //With that material object we can extract the dragCoefficient using the helper function above.
                            float dragC = (float)StageRecovery.GetMemberInfoValue(materialObject.GetType().GetMember("DragCoefficient")[0], materialObject);
                            //Now we calculate the RCParameter. Simple addition of this doesn't result in perfect results for Vt with parachutes with different diameter or drag coefficients
                            //But it works perfectly for mutiple identical parachutes (the normal case)
                            pChutes += dragC * (float)Math.Pow(diameter, 2);
                        }
                        realChuteInUse = true;
                    }
                    else if (part.Modules.Contains("RealChuteFAR")) //RealChute Lite for FAR
                    {
                        PartModule realChute = part.Modules["RealChuteFAR"];
                        float      diameter  = (float)realChute.Fields.GetValue("deployedDiameter");
                        // = float.Parse(realChute.moduleValues.GetValue("deployedDiameter"));
                        float dragC = 1.0f; //float.Parse(realChute.moduleValues.GetValue("staticCd"));
                        pChutes += dragC * (float)Math.Pow(diameter, 2);

                        realChuteInUse = true;
                    }
                    else if (!realChuteInUse && part.Modules.Contains("ModuleParachute"))
                    {
                        double scale = 1.0;
                        //check for Tweakscale and modify the area appropriately
                        if (part.Modules.Contains("TweakScale"))
                        {
                            PartModule tweakScale = part.Modules["TweakScale"];
                            double     currentScale = 100, defaultScale = 100;
                            double.TryParse(tweakScale.Fields.GetValue("currentScale").ToString(), out currentScale);
                            double.TryParse(tweakScale.Fields.GetValue("defaultScale").ToString(), out defaultScale);
                            scale = currentScale / defaultScale;
                        }

                        ModuleParachute mp = (ModuleParachute)part.Modules["ModuleParachute"];
                        //dragCoeff += part.mass * mp.fullyDeployedDrag;
                        pChutes += mp.areaDeployed * Math.Pow(scale, 2);
                    }

                    current.chuteArea += pChutes;
                }

                stages.Add(current);
            }

            ConsolidateStages();
            Debug.Log("[SR] Found " + stages.Count + " stages!");
        }
        internal void Update()
        {
            // Load Application Launcher
            if (settingsWindow.launcherButton == null && settings.useStockToolbar)
            {
                OnGUIApplicationLauncherReady();
                if (settingsWindow.showWindow)
                {
                    settingsWindow.launcherButton.SetTrue();
                }
            }

            // Destroy application launcher
            if (settingsWindow.launcherButton != null && settings.useStockToolbar == false)
            {
                removeApplicationLauncher();
            }

            foreach (Part p in FlightGlobals.ActiveVessel.parts)
            {
                if (p.Modules.OfType <ModuleParachute>().Any())
                {
                    StackIcon chuteIcon = Staging.FindIcon(p);
                    if (chuteIcon != null)
                    {
                        if (origTexture == null)
                        {
                            // First time through, set original texture
                            origTexture = chuteIcon.Bg;
                        }
                        else
                        {
                            // Other times, reset to original first then change below as needed
                            chuteIcon.Bg = origTexture;
                            p.stackIcon.SetBgColor(Color.white);
                        }

                        ModuleParachute chute = p.Modules.GetModules <ModuleParachute>().First();

                        if (settings.resetOnlyDeployWhenSafe)
                        {
                            chute.deployAltitude             = 500f;
                            chute.minAirPressureToOpen       = 0.01f;
                            settings.resetOnlyDeployWhenSafe = false;
                        }

                        if (chute.deploymentState == ModuleParachute.deploymentStates.STOWED && FlightGlobals.ActiveVessel.atmDensity > 0)
                        {
                            if (chute.deploySafe == "Safe")
                            {
                                if (settings.clearBackground)
                                {
                                    chuteIcon.Bg = settings.safeTexture;
                                }
                                else
                                {
                                    p.stackIcon.SetBgColor(settings.safeColor);
                                }
                            }
                            if (chute.deploySafe == "Risky")
                            {
                                if (settings.clearBackground)
                                {
                                    chuteIcon.Bg = settings.riskyTexture;
                                }
                                else
                                {
                                    p.stackIcon.SetBgColor(settings.riskyColor);
                                }
                            }
                            if (chute.deploySafe == "Unsafe")
                            {
                                if (settings.clearBackground)
                                {
                                    chuteIcon.Bg = settings.unSafeTexture;
                                }
                                else
                                {
                                    p.stackIcon.SetBgColor(settings.unSafeColor);
                                }
                            }
                        }

                        if (settings.onlyDeployWhenSafe && chute.deploymentState == ModuleParachute.deploymentStates.ACTIVE && FlightGlobals.ActiveVessel.atmDensity > 0)
                        {
                            if (chute.deploySafe == "Safe")
                            {
                                p.stackIcon.SetIconColor(settings.safeColor);
                                chute.deployAltitude       = (float)FlightGlobals.ActiveVessel.altitude;
                                chute.minAirPressureToOpen = 0.01f;
                            }
                            else
                            {
                                p.stackIcon.SetIconColor(settings.riskyColor);
                                chute.deployAltitude       = 100f;
                                chute.minAirPressureToOpen = 100f;
                            }
                        }
                    }
                }
            }
        }