public override void OnStart(StartState state)
        {
            // parent OnStart
            base.OnStart(state);

            module = Utils.getModuleByType<ModuleReactionWheel>(base.part);
        }
예제 #2
0
        public void Start()
        {
            foreach (ConfigNode node in part.partInfo.partConfig.GetNodes("MODULE"))
            {
                if (node.GetValue("name") == "SaturableRW")
                {
                    torqueCurve.Load(node.GetNode("torqueCurve"));

                    bleedRate.Load(node.GetNode("bleedRate"));

                    break;
                }
            }

            wheelRef = part.Modules.GetModule <ModuleReactionWheel> ();

            // Float curve initialization.

            maxRollTorque  = wheelRef.RollTorque;
            maxPitchTorque = wheelRef.PitchTorque;
            maxYawTorque   = wheelRef.YawTorque;

            saturationLimit = (maxPitchTorque + maxYawTorque + maxRollTorque) * saturationScale / 3;

            if (HighLogic.LoadedSceneIsFlight)
            {
                // Remember reference torque values.

                LoadConfig();

                StartCoroutine(RegisterWheel());
            }
        }
예제 #3
0
 // Disable all UI buttons and action groups, except the authority limiter slider.
 // RW torque can still be tweaked/disabled trough the renamed for clarity "Reaction Wheel Autority" GUI
 // TODO : reenable Normal/SAS/Pilot mode switch if strictMode is disabled
 private static void TweakUI(ModuleReactionWheel rw)
 {
     foreach (BaseField f in rw.Fields)
     {
         if (f.name.Equals("actuatorModeCycle") || f.name.Equals("stateString"))
         {
             f.guiActive       = false;
             f.guiActiveEditor = false;
         }
         if (f.name.Equals("authorityLimiter"))
         {
             f.guiName = "Reaction Wheel Authority";
         }
         // Debug.Log("RW Fields : guiName=" + f.guiName + ", name=" + f.name + ", guiActive=" + f.guiActive + ", guiActiveEditor=" + f.guiActiveEditor);
     }
     foreach (BaseEvent e in rw.Events)
     {
         if (e.name.Equals("OnToggle"))
         {
             e.guiActive       = false;
             e.guiActiveEditor = false;
         }
         // Debug.Log("RW Events : guiName=" + e.guiName + ", name=" + e.name + ", guiActive=" + e.guiActive + ", guiActiveEditor=" + e.guiActiveEditor);
     }
     foreach (BaseAction a in rw.Actions)
     {
         a.active = false;
         // Debug.Log("RW Actions : guiName=" + a.guiName + ", name=" + a.name + ", active=" + a.active);
     }
 }
        private void updateUsage(float rate)
        {
            if (module == null)
            {
                module = Utils.getModuleByType<ModuleReactionWheel>(base.part);
                return;
            }

            // usage due to time
            float timeUsage = usageUtils.getPartUsageInTime(rate);

            // usage modifier
            float usageMod = 1.0f;

            // usage when reaction wheels are used
            // when the wheels are active in all three axis inputSum = 3,
            // so, 100% all-axis activate shortens the lifespan by half
            usageMod += (module.inputSum / 3.0f);

            // also, add 0.2f when the wheel is enabled
            if (module.wheelState == ModuleReactionWheel.WheelState.Active)
            {
                usageMod += 0.2f;
            }

            conditionReactionWheels -= timeUsage * usageMod * usageUtils.GLOBAL_MOD;
        }
 // Reaction wheel stops working
 protected override void FailPart()
 {
     rw = part.FindModuleImplementing <ModuleReactionWheel>();
     if (!rw.isEnabled && rw.wheelState != ModuleReactionWheel.WheelState.Active)
     {
         return;
     }
     rw.isEnabled  = false;
     rw.wheelState = ModuleReactionWheel.WheelState.Broken;
     if (OhScrap.highlight)
     {
         OhScrap.SetFailedHighlight();
     }
     if (message)
     {
         return;
     }
     message = true;
     if (rw.wheelState != ModuleReactionWheel.WheelState.Broken)
     {
         Debug.Log("[OhScrap]: " + SYP.ID + "'s reaction wheels have failed");
     }
     if (vessel.vesselType != VesselType.Debris)
     {
         ScreenMessages.PostScreenMessage("A reaction wheel has failed");
     }
 }
예제 #6
0
 protected override void DI_Start(StartState state)
 {
     if (HighLogic.LoadedSceneIsFlight)
     {
         this.torqueModule = this.part.Modules.OfType <ModuleReactionWheel>().Single();
     }
 }
 protected override void Overrides()
 {
     Fields["displayChance"].guiName = "Chance of Reaction Wheel Failure";
     Fields["safetyRating"].guiName = "Reaction Wheel Safety Rating";
     failureType = "Reaction Wheel Failure";
     remoteRepairable = true;
     rw = part.FindModuleImplementing<ModuleReactionWheel>();
 }
 public override bool FailureAllowed()
 {
     rw = part.FindModuleImplementing <ModuleReactionWheel>();
     if (!rw.isEnabled && rw.wheelState != ModuleReactionWheel.WheelState.Active)
     {
         return(false);
     }
     return(HighLogic.CurrentGame.Parameters.CustomParams <UPFMSettings>().ReactionWheelFailureModuleAllowed);
 }
예제 #9
0
 internal ReactionWheel(Part part)
 {
     Part          = part;
     reactionWheel = part.InternalPart.Module <ModuleReactionWheel> ();
     if (reactionWheel == null)
     {
         throw new ArgumentException("Part is not a reaction wheel");
     }
 }
예제 #10
0
 internal ReactionWheel(Part part)
 {
     this.part     = part;
     reactionWheel = part.InternalPart.Module <ModuleReactionWheel> ();
     if (reactionWheel == null)
     {
         throw new ArgumentException("Part does not have a ModuleReactionWheel PartModule");
     }
 }
 // Reaction wheel stops working
 public override void FailPart()
 {
     rw            = part.FindModuleImplementing <ModuleReactionWheel>();
     rw.isEnabled  = false;
     rw.wheelState = ModuleReactionWheel.WheelState.Broken;
     if (OhScrap.highlight)
     {
         OhScrap.SetFailedHighlight();
     }
     hasFailed = true;
 }
 private void SetReactionWheelInfo()
 {
     moduleReactionWheel = selectedPart.GetModule <ModuleReactionWheel>();
     if (moduleReactionWheel != null)
     {
         infoItems.Add(PartInfoItem.Create("Reaction Wheel Torque"));
         infoItems.Add(PartInfoItem.Create("\tPitch", moduleReactionWheel.PitchTorque.ToTorque()));
         infoItems.Add(PartInfoItem.Create("\tRoll", moduleReactionWheel.RollTorque.ToTorque()));
         infoItems.Add(PartInfoItem.Create("\tYaw", moduleReactionWheel.YawTorque.ToTorque()));
         for (int i = 0; i < moduleReactionWheel.inputResources.Count; ++i)
         {
             moduleResource = moduleReactionWheel.inputResources[i];
             infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.rate.ToRate()));
         }
     }
 }
예제 #13
0
        public void Start()
        {
            if (MandatoryRCSSettings.featureReactionWheels)
            {
                // Does this RW respond to pilot/SAS input ?
                if (MandatoryRCSSettings.customizedWheels)
                {
                    bool isDefinedInCFG = false;
                    foreach (ConfigNode node in part.partInfo.partConfig.GetNodes("MODULE"))
                    {
                        if (node.GetValue("name") == "ModuleTorqueController")
                        {
                            isDefinedInCFG = node.TryGetValue("isControllable", ref isControllable);
                            break;
                        }
                    }
                    // If not defined in the module CFG, default rule is that pods and cockpits are not controllable, but RW parts and probes are.
                    if (!isDefinedInCFG)
                    {
                        isControllable = (part.CrewCapacity > 0) ? false : true;
                    }
                }
                else
                {
                    isControllable = true;
                }

                // We do the torque calculations only when in flight
                if (HighLogic.LoadedSceneIsFlight)
                {
                    vessel.OnFlyByWire          += new FlightInputCallback(UpdateTorque);
                    vessel.OnPreAutopilotUpdate += new FlightInputCallback(GetPilotInput);
                    callbackIsActive             = true;
                }
                else if (HighLogic.LoadedSceneIsEditor)
                {
                    rwmodule = part.Modules.GetModule <ModuleReactionWheel>();

                    if (rwmodule == null)
                    {
                        return;
                    }

                    TweakUI(rwmodule);
                }
            }
        }
예제 #14
0
        public void FixedUpdate()
        {
            if (!(HighLogic.LoadedSceneIsFlight && FlightGlobals.ready))
            {
                return;
            }



            vm = vessel.vesselModules.OfType <VesselModuleRotation>().First();
            tc = part.Modules.GetModule <ModuleTorqueController>();
            rw = part.Modules.GetModule <ModuleReactionWheel>();

            angularVelocity = vessel.angularVelocity.magnitude;
            rollTorque      = rw.RollTorque;
            pitchTorque     = rw.PitchTorque;
            yawTorque       = rw.YawTorque;

            inputVectorDelta = (rw.inputVector * TimeWarp.fixedDeltaTime).ToString("0.0000");
        }
예제 #15
0
 protected override void FailPart()
 {
     rw            = part.FindModuleImplementing <ModuleReactionWheel>();
     rw.isEnabled  = false;
     rw.wheelState = ModuleReactionWheel.WheelState.Broken;
     if (UPFM.highlight)
     {
         UPFM.SetFailedHighlight();
     }
     if (message)
     {
         return;
     }
     message = true;
     if (rw.wheelState != ModuleReactionWheel.WheelState.Broken)
     {
         Debug.Log("[UPFM]: " + SYP.ID + "'s reaction wheels have failed");
     }
     ScreenMessages.PostScreenMessage("A reaction wheel has failed");
 }
예제 #16
0
 public void upgradePartModule()
 {
     computercoreType = upgradedName;
     if (nameStr == "")
     {
         ConfigNode[]  namelist = ComputerCore.getNames();
         System.Random rands    = new System.Random();
         ConfigNode    myName   = namelist[rands.Next(0, namelist.Length)];
         nameStr = myName.GetValue("name");
     }
     if (part.Modules.Contains("ModuleReactionWheel"))
     {
         ModuleReactionWheel reaction_wheel = this.part.Modules["ModuleReactionWheel"] as ModuleReactionWheel;
         reaction_wheel.PitchTorque = 5;
         reaction_wheel.RollTorque  = 5;
         reaction_wheel.YawTorque   = 5;
     }
     isupgraded       = true;
     _experiment_node = GameDatabase.Instance.GetConfigNodes("EXPERIMENT_DEFINITION").FirstOrDefault(nd => nd.GetValue("id") == experimentID);
 }
예제 #17
0
파일: AJERotor.cs 프로젝트: emtee40/AJE-1
        public override void CreateEngine()
        {
            if (maxEngineTemp == 0d)
            {
                maxEngineTemp = part.maxTemp;
            }

            float omega = rpm * 0.1047f;

//            power *= 745.7f;
            engineSolver = new SolverRotor(omega, r, weight, power * 745.7f, 1.2f, VTOLbuff, BSFC, useOxygen);
            sas          = part.FindModuleImplementing <ModuleReactionWheel>();
            if (sas != null)
            {
                sasP = sas.PitchTorque;
                sasY = sas.YawTorque;
                sasR = sas.RollTorque;
            }

            useAtmCurve = atmChangeFlow = useVelCurve = useAtmCurveIsp = useVelCurveIsp = false;
        }
예제 #18
0
        private void AnalyzeReactionWheels()
        {
            torqueReactionWheel.Reset();

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

                List <ModuleReactionWheel> mlist = p.Modules.GetModules <ModuleReactionWheel>();

                for (int m = 0; m < mlist.Count; m++)
                {
                    Vector3             pos;
                    Vector3             neg;
                    ModuleReactionWheel rw = mlist[m];
                    rw.GetPotentialTorque(out pos, out neg);
                    torqueReactionWheel.Add(pos);
                    torqueReactionWheel.Add(-neg);
                }
            }
        }
예제 #19
0
        protected void setupModules()
        {
            //Command
            ModuleCommand command = this.part.FindModuleImplementing <ModuleCommand>();

            if (command != null)
            {
                command.enabled   = groundOpsMode;
                command.isEnabled = groundOpsMode;
            }

            //Solar Panel
            ModuleDeployableSolarPanel solarPanel = this.part.FindModuleImplementing <ModuleDeployableSolarPanel>();

            if (solarPanel != null)
            {
                solarPanel.enabled   = groundOpsMode;
                solarPanel.isEnabled = groundOpsMode;
            }

            //Reaction Wheel
            ModuleReactionWheel reactionWheel = this.part.FindModuleImplementing <ModuleReactionWheel>();

            if (reactionWheel != null)
            {
                reactionWheel.enabled   = groundOpsMode;
                reactionWheel.isEnabled = groundOpsMode;
            }

            //SAS
            ModuleSAS sas = this.part.FindModuleImplementing <ModuleSAS>();

            if (sas != null)
            {
                sas.enabled   = groundOpsMode;
                sas.isEnabled = groundOpsMode;
            }
        }
        public override void OnStart(StartState state)
        {
            _reactionWheel = part.FindModuleImplementing <ModuleReactionWheel>();

            if (_reactionWheel == null)
            {
                return;
            }

            var actuatorModeCycleField = _reactionWheel.Fields[nameof(_reactionWheel.actuatorModeCycle)];
            var authorityLimiterField  = _reactionWheel.Fields[nameof(_reactionWheel.authorityLimiter)];
            var stateStringField       = _reactionWheel.Fields[nameof(_reactionWheel.stateString)];
            var onToggleEvent          = _reactionWheel.Events[nameof(_reactionWheel.OnToggle)];

            actuatorModeCycleField.group = new BasePAWGroup(Group, GroupTitle, false);
            authorityLimiterField.group  = new BasePAWGroup(Group, GroupTitle, false);
            stateStringField.group       = new BasePAWGroup(Group, GroupTitle, false);
            onToggleEvent.group          = new BasePAWGroup(Group, GroupTitle, false);

            maxRollTorque  = (double)(decimal)_reactionWheel.RollTorque;
            maxPitchTorque = (double)(decimal)_reactionWheel.PitchTorque;
            maxYawTorque   = (double)(decimal)_reactionWheel.YawTorque;
        }
예제 #21
0
파일: AJERotor.cs 프로젝트: camlost2/AJE
        public override void OnStart(StartState state)
        {
            if (state == StartState.Editor)
            {
                return;
            }
            if (vessel == null)
            {
                return;
            }
            engine = new EngineWrapper(part);
            engine.IspMultiplier    = IspMultiplier;
            engine.idle             = idle;
            engine.useVelocityCurve = false;
            engine.ThrustUpperLimit = maxThrust;
            float omega = rpm * 0.1047f;

//            power *= 745.7f;
            aje  = new AJERotorSolver(omega, r, weight, power * 745.7f, 1.2f, VTOLbuff);
            sas  = (ModuleReactionWheel)part.Modules["ModuleReactionWheel"];
            sasP = sas.PitchTorque;
            sasY = sas.YawTorque;
            sasR = sas.RollTorque;
        }
 private void SetReactionWheelInfo()
 {
     moduleReactionWheel = selectedPart.GetModule<ModuleReactionWheel>();
     if (moduleReactionWheel != null)
     {
         infoItems.Add(PartInfoItem.Create("Reaction Wheel Torque"));
         infoItems.Add(PartInfoItem.Create("\tPitch", moduleReactionWheel.PitchTorque.ToTorque()));
         infoItems.Add(PartInfoItem.Create("\tRoll", moduleReactionWheel.RollTorque.ToTorque()));
         infoItems.Add(PartInfoItem.Create("\tYaw", moduleReactionWheel.YawTorque.ToTorque()));
         for (int i = 0; i < moduleReactionWheel.resHandler.inputResources.Count; ++i)
         {
             moduleResource = moduleReactionWheel.resHandler.inputResources[i];
             infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.rate.ToRate()));
         }
     }
 }
예제 #23
0
        /// <summary>
        /// Start
        /// </summary>
        /// <param name="state"></param>
        public override void OnStart(StartState state)
        {
            GSA.Durability.Debug.Log("GSA Durability: [OnStart][" + state.ToString() + "]: " + this.name);
            base.OnStart(state);
            try
            {
                _state = state;
                AvailablePart currentPartInfo = PartLoader.getPartInfoByName(part.name.Replace("(Clone)", ""));
                _initCost = currentPartInfo.cost;
                if (state == StartState.Editor)
                {
                    return;
                }
                if (part.Resources.Contains("Quality"))
                {
                    quality = (part.Resources["Quality"].amount / (part.Resources["Quality"].maxAmount / 100)) / 100;
                }

                if (basicWear.findCurveMinMaxInterations == 0)
                {
                    basicWear = new FloatCurve();
                    basicWear.Add(0.1f, 0.69f);
                    basicWear.Add(0.5f, 0.000181f);
                    basicWear.Add(1f, 0.00001f);
                }
                _currentWear = basicWear.Evaluate((float)quality);
                _lastUpdateTime = vessel.missionTime;
                _sun = Planetarium.fetch.Sun;
                //gameObject.AddComponent(typeof(LineRenderer));

                if (part.Modules.Contains("ModuleCommand"))
                {
                    _command = (ModuleCommand)part.Modules["ModuleCommand"];
                    GSA.Durability.Debug.Log("GSA Durability: [OnStart]: _command = " + _command.name);
                }

                if (part.Modules.Contains("ModuleReactionWheel"))
                {
                    _reactionWheel = (ModuleReactionWheel)part.Modules["ModuleReactionWheel"];
                    GSA.Durability.Debug.Log("GSA Durability: [OnStart]: _reactionWheel = " + _reactionWheel.name);
                }

                if (part.Modules.Contains("ModuleEngines"))
                {
                    _engine = (ModuleEngines)part.Modules["ModuleEngines"];
                    GSA.Durability.Debug.Log("GSA Durability: [OnStart]: _engine = " + _engine.name);
                }
                if (part.Modules.Contains("ModuleScienceExperiment"))
                {
                    _scienceExperiment = (ModuleScienceExperiment)part.Modules["ModuleScienceExperiment"];
                    GSA.Durability.Debug.Log("GSA Durability: [OnStart]: _scienceExperiment = " + _scienceExperiment.name);
                }

                checkStatus();
                setEventLabel();
            }
            catch (Exception ex)
            {
                GSA.Durability.Debug.LogError("GSA Durability: [OnStart]: Message: " + ex.Message);
                GSA.Durability.Debug.LogError("GSA Durability: [OnStart]: StackTrace: " + ex.StackTrace);
            }

            GSA.Durability.Debug.Log("GSA Durability: [OnStart]: quality:" + quality.ToString());
            GSA.Durability.Debug.Log("GSA Durability: [OnStart]: damageRate: " + _currentWear.ToString("0.000000"));
            GSA.Durability.Debug.Log("GSA Durability: [OnStart]: vessel.missionTime: " + vessel.missionTime.ToString());
            GSA.Durability.Debug.Log("GSA Durability: [OnStart]: lastReduceRange: " + lastReduceRange.ToString());
            GSA.Durability.Debug.Log("GSA Durability: [OnStart]: lastUpdateTime: " + _lastUpdateTime.ToString());
            GSA.Durability.Debug.Log("GSA Durability: [OnStart]: maxRepair: " + maxRepair.ToString());
            GSA.Durability.Debug.Log("GSA Durability: [OnStart]: canRepair: " + canRepair.ToString());
        }
예제 #24
0
        public void Update(Vessel vessel)
        {
            if (vessel.rigidbody == null)
            {
                return;                           //if we try to update before rigidbodies exist we spam the console with NullPointerExceptions.
            }
            //if (vessel.packed) return;

            // To investigate some strange error
            if ((vessel.mainBody == null || (object)(vessel.mainBody) == null) && counter == 0)
            {
                if ((object)(vessel.mainBody) == null)
                {
                    MechJebCore.print("vessel.mainBody is proper null");
                }
                else
                {
                    MechJebCore.print("vessel.mainBody is Unity null");
                }

                counter = counter++ % 100;
            }


            time   = Planetarium.GetUniversalTime();
            deltaT = TimeWarp.fixedDeltaTime;

            CoM = vessel.findWorldCenterOfMass();
            up  = (CoM - vessel.mainBody.position).normalized;

            Rigidbody rigidBody = vessel.rootPart.rigidbody;

            if (rigidBody != null)
            {
                rootPartPos = rigidBody.position;
            }

            north                 = Vector3d.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - CoM).normalized;
            east                  = vessel.mainBody.getRFrmVel(CoM).normalized;
            forward               = vessel.GetTransform().up;
            rotationSurface       = Quaternion.LookRotation(north, up);
            rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface);

//            velocityVesselOrbit = vessel.orbit.GetVel();
//            velocityVesselOrbitUnit = velocityVesselOrbit.normalized;
//            velocityVesselSurface = velocityVesselOrbit - vessel.mainBody.getRFrmVel(CoM);
//            velocityVesselSurfaceUnit = velocityVesselSurface.normalized;
            velocityMainBodySurface = rotationSurface * vessel.srf_velocity;

            horizontalOrbit   = Vector3d.Exclude(up, vessel.obt_velocity).normalized;
            horizontalSurface = Vector3d.Exclude(up, vessel.srf_velocity).normalized;

            angularVelocity = Quaternion.Inverse(vessel.GetTransform().rotation) * vessel.rigidbody.angularVelocity;

            radialPlusSurface = Vector3d.Exclude(vessel.srf_velocity, up).normalized;
            radialPlus        = Vector3d.Exclude(vessel.obt_velocity, up).normalized;
            normalPlusSurface = -Vector3d.Cross(radialPlusSurface, vessel.srf_velocity.normalized);
            normalPlus        = -Vector3d.Cross(radialPlus, vessel.obt_velocity.normalized);

            gravityForce = FlightGlobals.getGeeForceAtPosition(CoM);
            localg       = gravityForce.magnitude;

            speedOrbital.value           = vessel.obt_velocity.magnitude;
            speedSurface.value           = vessel.srf_velocity.magnitude;
            speedVertical.value          = Vector3d.Dot(vessel.srf_velocity, up);
            speedSurfaceHorizontal.value = Vector3d.Exclude(up, vessel.srf_velocity).magnitude; //(velocityVesselSurface - (speedVertical * up)).magnitude;
            speedOrbitHorizontal         = (vessel.obt_velocity - (speedVertical * up)).magnitude;

            vesselHeading.value = rotationVesselSurface.eulerAngles.y;
            vesselPitch.value   = (rotationVesselSurface.eulerAngles.x > 180) ? (360.0 - rotationVesselSurface.eulerAngles.x) : -rotationVesselSurface.eulerAngles.x;
            vesselRoll.value    = (rotationVesselSurface.eulerAngles.z > 180) ? (rotationVesselSurface.eulerAngles.z - 360.0) : rotationVesselSurface.eulerAngles.z;

            altitudeASL.value = vessel.mainBody.GetAltitude(CoM);
            //RaycastHit sfc;
            //if (Physics.Raycast(CoM, -up, out sfc, (float)altitudeASL + 10000.0F, 1 << 15))
            //{
            //    altitudeTrue.value = sfc.distance;
            //}
            //else if (vessel.mainBody.pqsController != null)
            //{
            //    // from here: http://kerbalspaceprogram.com/forum/index.php?topic=10324.msg161923#msg161923
            //    altitudeTrue.value = vessel.mainBody.GetAltitude(CoM) - (vessel.mainBody.pqsController.GetSurfaceHeight(QuaternionD.AngleAxis(vessel.mainBody.GetLongitude(CoM), Vector3d.down) * QuaternionD.AngleAxis(vessel.mainBody.GetLatitude(CoM), Vector3d.forward) * Vector3d.right) - vessel.mainBody.pqsController.radius);
            //}
            //else
            //{
            //    altitudeTrue.value = vessel.mainBody.GetAltitude(CoM);
            //}

            //double surfaceAltitudeASL = altitudeASL - altitudeTrue;

            double surfaceAltitudeASL = vessel.mainBody.pqsController != null ? vessel.pqsAltitude : 0d;

            altitudeTrue.value = altitudeASL - surfaceAltitudeASL;

            altitudeBottom = altitudeTrue;
            foreach (Part p in vessel.parts)
            {
                if (p.collider != null)
                {
                    Vector3d bottomPoint   = p.collider.ClosestPointOnBounds(vessel.mainBody.position);
                    double   partBottomAlt = vessel.mainBody.GetAltitude(bottomPoint) - surfaceAltitudeASL;
                    altitudeBottom = Math.Max(0, Math.Min(altitudeBottom, partBottomAlt));
                }
            }

            double atmosphericPressure = FlightGlobals.getStaticPressure(altitudeASL, vessel.mainBody);

            if (atmosphericPressure < vessel.mainBody.atmosphereMultiplier * 1e-6)
            {
                atmosphericPressure = 0;
            }
            atmosphericDensity      = FlightGlobals.getAtmDensity(atmosphericPressure);
            atmosphericDensityGrams = atmosphericDensity * 1000;

            orbitApA.value      = vessel.orbit.ApA;
            orbitPeA.value      = vessel.orbit.PeA;
            orbitPeriod.value   = vessel.orbit.period;
            orbitTimeToAp.value = vessel.orbit.timeToAp;
            if (vessel.orbit.eccentricity < 1)
            {
                orbitTimeToPe.value = vessel.orbit.timeToPe;
            }
            else
            {
                orbitTimeToPe.value = -vessel.orbit.meanAnomaly / (2 * Math.PI / vessel.orbit.period);
            }
            orbitLAN.value = vessel.orbit.LAN;
            orbitArgumentOfPeriapsis.value = vessel.orbit.argumentOfPeriapsis;
            orbitInclination.value         = vessel.orbit.inclination;
            orbitEccentricity.value        = vessel.orbit.eccentricity;
            orbitSemiMajorAxis.value       = vessel.orbit.semiMajorAxis;
            latitude.value  = vessel.mainBody.GetLatitude(CoM);
            longitude.value = MuUtils.ClampDegrees180(vessel.mainBody.GetLongitude(CoM));

            if (vessel.mainBody != Planetarium.fetch.Sun)
            {
                Vector3d delta = vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime() + 1) - vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime() - 1);
                Vector3d plUp  = Vector3d.Cross(vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime()) - vessel.mainBody.referenceBody.getPositionAtUT(Planetarium.GetUniversalTime()), vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime() + vessel.mainBody.orbit.period / 4) - vessel.mainBody.referenceBody.getPositionAtUT(Planetarium.GetUniversalTime() + vessel.mainBody.orbit.period / 4)).normalized;
                angleToPrograde = MuUtils.ClampDegrees360((((vessel.orbit.inclination > 90) || (vessel.orbit.inclination < -90)) ? 1 : -1) * ((Vector3)up).AngleInPlane(plUp, delta));
            }
            else
            {
                angleToPrograde = 0;
            }

            mainBody = vessel.mainBody;

            radius = (CoM - vessel.mainBody.position).magnitude;

            mass = massDrag = torqueThrustPYAvailable = 0;
            thrustVectorLastFrame   = new Vector3d();
            thrustVectorMaxThrottle = new Vector3d();
            thrustVectorMinThrottle = new Vector3d();
            torqueAvailable         = new Vector3d();
            rcsThrustAvailable      = new Vector6();
            rcsTorqueAvailable      = new Vector6();
            ctrlTorqueAvailable     = new Vector6();

            EngineInfo einfo = new EngineInfo(CoM);
            IntakeInfo iinfo = new IntakeInfo();

            parachutes = new List <ModuleParachute>();

            var rcsbal = vessel.GetMasterMechJeb().rcsbal;

            if (vessel.ActionGroups[KSPActionGroup.RCS] && rcsbal.enabled)
            {
                Vector3d rot = Vector3d.zero;
                foreach (Vector6.Direction dir6 in Enum.GetValues(typeof(Vector6.Direction)))
                {
                    Vector3d dir = Vector6.directions[dir6];
                    double[] throttles;
                    List <RCSSolver.Thruster> thrusters;
                    rcsbal.GetThrottles(dir, out throttles, out thrusters);
                    if (throttles != null)
                    {
                        for (int i = 0; i < throttles.Length; i++)
                        {
                            if (throttles[i] > 0)
                            {
                                Vector3d force = thrusters[i].GetThrust(dir, rot);
                                rcsThrustAvailable.Add(vessel.GetTransform().InverseTransformDirection(dir * Vector3d.Dot(force * throttles[i], dir)));
                            }
                        }
                    }
                }
            }

            hasMFE = false;

            foreach (Part p in vessel.parts)
            {
                if (p.IsPhysicallySignificant())
                {
                    double partMass = p.TotalMass();
                    mass     += partMass;
                    massDrag += partMass * p.maximum_drag;
                }

                if (vessel.ActionGroups[KSPActionGroup.RCS] && !rcsbal.enabled)
                {
                    foreach (ModuleRCS pm in p.Modules.OfType <ModuleRCS>())
                    {
                        double   maxT         = pm.thrusterPower;
                        Vector3d partPosition = p.Rigidbody.worldCenterOfMass - CoM;

                        if ((pm.isEnabled) && (!pm.isJustForShow))
                        {
                            foreach (Transform t in pm.thrusterTransforms)
                            {
                                Vector3d thrusterThrust = vessel.GetTransform().InverseTransformDirection(-t.up.normalized) * pm.thrusterPower;
                                rcsThrustAvailable.Add(thrusterThrust);
                                Vector3d thrusterTorque = Vector3.Cross(vessel.GetTransform().InverseTransformDirection(partPosition), thrusterThrust);
                                rcsTorqueAvailable.Add(thrusterTorque);
                            }
                        }
                    }
                }

                if (p is ControlSurface)
                {
                    Vector3d       partPosition = p.Rigidbody.worldCenterOfMass - CoM;
                    ControlSurface cs           = (p as ControlSurface);
                    Vector3d       airSpeed     = vessel.srf_velocity + Vector3.Cross(cs.Rigidbody.angularVelocity, cs.transform.position - cs.Rigidbody.position);
                    // Air Speed is velocityVesselSurface
                    // AddForceAtPosition seems to need the airspeed vector rotated with the flap rotation x its surface
                    Quaternion airSpeedRot   = Quaternion.AngleAxis(cs.ctrlSurfaceRange * cs.ctrlSurfaceArea, cs.transform.rotation * cs.pivotAxis);
                    Vector3    ctrlTroquePos = vessel.GetTransform().InverseTransformDirection(Vector3.Cross(partPosition, cs.getLiftVector(airSpeedRot * airSpeed)));
                    Vector3    ctrlTroqueNeg = vessel.GetTransform().InverseTransformDirection(Vector3.Cross(partPosition, cs.getLiftVector(Quaternion.Inverse(airSpeedRot) * airSpeed)));
                    ctrlTorqueAvailable.Add(ctrlTroquePos);
                    ctrlTorqueAvailable.Add(ctrlTroqueNeg);
                }

                if (p is CommandPod)
                {
                    torqueAvailable += Vector3d.one * Math.Abs(((CommandPod)p).rotPower);
                }

                foreach (VesselStatePartExtension vspe in vesselStatePartExtensions)
                {
                    vspe(p);
                }

                foreach (PartModule pm in p.Modules)
                {
                    if (!pm.isEnabled)
                    {
                        continue;
                    }

                    if (pm is ModuleReactionWheel)
                    {
                        ModuleReactionWheel rw = (ModuleReactionWheel)pm;
                        // I had to remove the test for active in .23 since the new ressource system reply to the RW that
                        // there is no energy available when the RW do tiny adjustement.
                        // I replaceed it with a test that check if there is electricity anywhere on the ship.
                        // Let's hope we don't get reaction wheel that use something else
                        //if (rw.wheelState == ModuleReactionWheel.WheelState.Active && !rw.stateString.Contains("Not enough"))
                        if (rw.wheelState == ModuleReactionWheel.WheelState.Active && vessel.HasElectricCharge())
                        {
                            torqueAvailable += new Vector3d(rw.PitchTorque, rw.RollTorque, rw.YawTorque);
                        }
                    }
                    else if (pm is ModuleEngines)
                    {
                        einfo.AddNewEngine(pm as ModuleEngines);
                    }
                    else if (pm is ModuleEnginesFX)
                    {
                        einfo.AddNewEngine(pm as ModuleEnginesFX);
                    }
                    else if (pm is ModuleResourceIntake)
                    {
                        iinfo.addIntake(pm as ModuleResourceIntake);
                    }
                    else if (pm is ModuleParachute)
                    {
                        parachutes.Add(pm as ModuleParachute);
                    }
                    else if (pm is ModuleControlSurface)
                    {
                        // TODO : Tweakable for ignorePitch / ignoreYaw  / ignoreRoll
                        ModuleControlSurface cs           = (pm as ModuleControlSurface);
                        Vector3d             partPosition = p.Rigidbody.worldCenterOfMass - CoM;

                        Vector3d airSpeed = vessel.srf_velocity + Vector3.Cross(cs.part.Rigidbody.angularVelocity, cs.transform.position - cs.part.Rigidbody.position);

                        Quaternion airSpeedRot = Quaternion.AngleAxis(cs.ctrlSurfaceRange * cs.ctrlSurfaceArea, cs.transform.rotation * Vector3.right);

                        Vector3 ctrlTroquePos = vessel.GetTransform().InverseTransformDirection(Vector3.Cross(partPosition, cs.getLiftVector(airSpeedRot * airSpeed)));
                        Vector3 ctrlTroqueNeg = vessel.GetTransform().InverseTransformDirection(Vector3.Cross(partPosition, cs.getLiftVector(Quaternion.Inverse(airSpeedRot) * airSpeed)));
                        ctrlTorqueAvailable.Add(ctrlTroquePos);
                        ctrlTorqueAvailable.Add(ctrlTroqueNeg);
                    }

                    if (pm.ClassName == "ModuleEngineConfigs" || pm.ClassName == "ModuleHybridEngine" || pm.ClassName == "ModuleHybridEngines")
                    {
                        hasMFE = true;
                    }

                    foreach (VesselStatePartModuleExtension vspme in vesselStatePartModuleExtensions)
                    {
                        vspme(pm);
                    }
                }
            }

            // Consider all the parachutes
            {
                bool tempParachuteDeployed = false;
                foreach (ModuleParachute p in parachutes)
                {
                    if (p.deploymentState == ModuleParachute.deploymentStates.DEPLOYED || p.deploymentState == ModuleParachute.deploymentStates.SEMIDEPLOYED)
                    {
                        tempParachuteDeployed = true;
                        break;
                    }
                }
                this.parachuteDeployed = tempParachuteDeployed;
            }

            torqueAvailable += Vector3d.Max(rcsTorqueAvailable.positive, rcsTorqueAvailable.negative);   // Should we use Max or Min ?
            torqueAvailable += Vector3d.Max(ctrlTorqueAvailable.positive, ctrlTorqueAvailable.negative); // Should we use Max or Min ?

            thrustVectorMaxThrottle += einfo.thrustMax;
            thrustVectorMinThrottle += einfo.thrustMin;
            thrustVectorLastFrame   += einfo.thrustCurrent;
            torqueThrustPYAvailable += einfo.torqueThrustPYAvailable;

            if (thrustVectorMaxThrottle.magnitude == 0 && vessel.ActionGroups[KSPActionGroup.RCS])
            {
                rcsThrust = true;
                thrustVectorMaxThrottle += (Vector3d)(vessel.transform.up) * rcsThrustAvailable.down;
            }
            else
            {
                rcsThrust = false;
            }

            // Convert the resource information from the einfo and iinfo format
            // to the more useful ResourceInfo format.
            resources = new Dictionary <int, ResourceInfo>();
            foreach (var info in einfo.resourceRequired)
            {
                int id  = info.Key;
                var req = info.Value;
                resources[id] = new ResourceInfo(
                    PartResourceLibrary.Instance.GetDefinition(id),
                    req.requiredLastFrame,
                    req.requiredAtMaxThrottle,
                    iinfo.getIntakes(id));
            }

            int intakeAirId = PartResourceLibrary.Instance.GetDefinition("IntakeAir").id;

            intakeAir           = 0;
            intakeAirNeeded     = 0;
            intakeAirAtMax      = 0;
            intakeAirAllIntakes = 0;
            if (resources.ContainsKey(intakeAirId))
            {
                intakeAir           = resources[intakeAirId].intakeProvided;
                intakeAirAllIntakes = resources[intakeAirId].intakeAvailable;
                intakeAirNeeded     = resources[intakeAirId].required;
                intakeAirAtMax      = resources[intakeAirId].requiredAtMaxThrottle;
            }

            angularMomentum = new Vector3d(angularVelocity.x * MoI.x, angularVelocity.y * MoI.y, angularVelocity.z * MoI.z);

            inertiaTensor = new Matrix3x3();
            foreach (Part p in vessel.parts)
            {
                if (p.Rigidbody == null)
                {
                    continue;
                }

                //Compute the contributions to the vessel inertia tensor due to the part inertia tensor
                Vector3d   principalMoments = p.Rigidbody.inertiaTensor;
                Quaternion princAxesRot     = Quaternion.Inverse(vessel.GetTransform().rotation) * p.transform.rotation * p.Rigidbody.inertiaTensorRotation;
                Quaternion invPrincAxesRot  = Quaternion.Inverse(princAxesRot);

                for (int i = 0; i < 3; i++)
                {
                    Vector3d iHat = Vector3d.zero;
                    iHat[i] = 1;
                    for (int j = 0; j < 3; j++)
                    {
                        Vector3d jHat = Vector3d.zero;
                        jHat[j]              = 1;
                        inertiaTensor[i, j] += Vector3d.Dot(iHat, princAxesRot * Vector3d.Scale(principalMoments, invPrincAxesRot * jHat));
                    }
                }

                //Compute the contributions to the vessel inertia tensor due to the part mass and position
                double  partMass     = p.TotalMass();
                Vector3 partPosition = vessel.GetTransform().InverseTransformDirection(p.Rigidbody.worldCenterOfMass - CoM);

                for (int i = 0; i < 3; i++)
                {
                    inertiaTensor[i, i] += partMass * partPosition.sqrMagnitude;

                    for (int j = 0; j < 3; j++)
                    {
                        inertiaTensor[i, j] += -partMass * partPosition[i] * partPosition[j];
                    }
                }
            }

            MoI             = new Vector3d(inertiaTensor[0, 0], inertiaTensor[1, 1], inertiaTensor[2, 2]);
            angularMomentum = inertiaTensor * angularVelocity;
        }
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
     module = base.part.FindModuleImplementing<ModuleReactionWheel>();
 }
예제 #26
0
 public override void RepairPart()
 {
     rw            = part.FindModuleImplementing <ModuleReactionWheel>();
     rw.isEnabled  = true;
     rw.wheelState = ModuleReactionWheel.WheelState.Active;
 }
예제 #27
0
        public void Update(Vessel vessel)
        {
            if (vessel.rigidbody == null)
            {
                return; //if we try to update before rigidbodies exist we spam the console with NullPointerExceptions.
            }
            //if (vessel.packed) return;

            time   = Planetarium.GetUniversalTime();
            deltaT = TimeWarp.fixedDeltaTime;

            CoM = vessel.findWorldCenterOfMass();
            up  = (CoM - vessel.mainBody.position).normalized;

            Rigidbody rigidBody = vessel.rootPart.rigidbody;

            if (rigidBody != null)
            {
                rootPartPos = rigidBody.position;
            }

            north                 = Vector3d.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - CoM).normalized;
            east                  = vessel.mainBody.getRFrmVel(CoM).normalized;
            forward               = vessel.GetTransform().up;
            rotationSurface       = Quaternion.LookRotation(north, up);
            rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface);

            velocityVesselOrbit       = vessel.orbit.GetVel();
            velocityVesselOrbitUnit   = velocityVesselOrbit.normalized;
            velocityVesselSurface     = velocityVesselOrbit - vessel.mainBody.getRFrmVel(CoM);
            velocityVesselSurfaceUnit = velocityVesselSurface.normalized;
            velocityMainBodySurface   = rotationSurface * velocityVesselSurface;

            horizontalOrbit   = Vector3d.Exclude(up, velocityVesselOrbit).normalized;
            horizontalSurface = Vector3d.Exclude(up, velocityVesselSurface).normalized;

            angularVelocity = Quaternion.Inverse(vessel.GetTransform().rotation) * vessel.rigidbody.angularVelocity;

            radialPlusSurface = Vector3d.Exclude(velocityVesselSurface, up).normalized;
            radialPlus        = Vector3d.Exclude(velocityVesselOrbit, up).normalized;
            normalPlusSurface = -Vector3d.Cross(radialPlusSurface, velocityVesselSurfaceUnit);
            normalPlus        = -Vector3d.Cross(radialPlus, velocityVesselOrbitUnit);

            gravityForce = FlightGlobals.getGeeForceAtPosition(CoM);
            localg       = gravityForce.magnitude;

            speedOrbital.value           = velocityVesselOrbit.magnitude;
            speedSurface.value           = velocityVesselSurface.magnitude;
            speedVertical.value          = Vector3d.Dot(velocityVesselSurface, up);
            speedSurfaceHorizontal.value = (velocityVesselSurface - (speedVertical * up)).magnitude;
            speedOrbitHorizontal         = (velocityVesselOrbit - (speedVertical * up)).magnitude;

            vesselHeading.value = rotationVesselSurface.eulerAngles.y;
            vesselPitch.value   = (rotationVesselSurface.eulerAngles.x > 180) ? (360.0 - rotationVesselSurface.eulerAngles.x) : -rotationVesselSurface.eulerAngles.x;
            vesselRoll.value    = (rotationVesselSurface.eulerAngles.z > 180) ? (rotationVesselSurface.eulerAngles.z - 360.0) : rotationVesselSurface.eulerAngles.z;

            altitudeASL.value = vessel.mainBody.GetAltitude(CoM);
            RaycastHit sfc;

            if (Physics.Raycast(CoM, -up, out sfc, (float)altitudeASL + 10000.0F, 1 << 15))
            {
                altitudeTrue.value = sfc.distance;
            }
            else if (vessel.mainBody.pqsController != null)
            {
                // from here: http://kerbalspaceprogram.com/forum/index.php?topic=10324.msg161923#msg161923
                altitudeTrue.value = vessel.mainBody.GetAltitude(CoM) - (vessel.mainBody.pqsController.GetSurfaceHeight(QuaternionD.AngleAxis(vessel.mainBody.GetLongitude(CoM), Vector3d.down) * QuaternionD.AngleAxis(vessel.mainBody.GetLatitude(CoM), Vector3d.forward) * Vector3d.right) - vessel.mainBody.pqsController.radius);
            }
            else
            {
                altitudeTrue.value = vessel.mainBody.GetAltitude(CoM);
            }

            double surfaceAltitudeASL = altitudeASL - altitudeTrue;

            altitudeBottom = altitudeTrue;
            foreach (Part p in vessel.parts)
            {
                if (p.collider != null)
                {
                    Vector3d bottomPoint   = p.collider.ClosestPointOnBounds(vessel.mainBody.position);
                    double   partBottomAlt = vessel.mainBody.GetAltitude(bottomPoint) - surfaceAltitudeASL;
                    altitudeBottom = Math.Max(0, Math.Min(altitudeBottom, partBottomAlt));
                }
            }

            double atmosphericPressure = FlightGlobals.getStaticPressure(altitudeASL, vessel.mainBody);

            if (atmosphericPressure < vessel.mainBody.atmosphereMultiplier * 1e-6)
            {
                atmosphericPressure = 0;
            }
            atmosphericDensity      = FlightGlobals.getAtmDensity(atmosphericPressure);
            atmosphericDensityGrams = atmosphericDensity * 1000;

            orbitApA.value      = vessel.orbit.ApA;
            orbitPeA.value      = vessel.orbit.PeA;
            orbitPeriod.value   = vessel.orbit.period;
            orbitTimeToAp.value = vessel.orbit.timeToAp;
            if (vessel.orbit.eccentricity < 1)
            {
                orbitTimeToPe.value = vessel.orbit.timeToPe;
            }
            else
            {
                orbitTimeToPe.value = -vessel.orbit.meanAnomaly / (2 * Math.PI / vessel.orbit.period);
            }
            orbitLAN.value = vessel.orbit.LAN;
            orbitArgumentOfPeriapsis.value = vessel.orbit.argumentOfPeriapsis;
            orbitInclination.value         = vessel.orbit.inclination;
            orbitEccentricity.value        = vessel.orbit.eccentricity;
            orbitSemiMajorAxis.value       = vessel.orbit.semiMajorAxis;
            latitude.value  = vessel.mainBody.GetLatitude(CoM);
            longitude.value = RTUtil.ClampDegrees180(vessel.mainBody.GetLongitude(CoM));

            if (vessel.mainBody != Planetarium.fetch.Sun)
            {
                Vector3d delta = vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime() + 1) - vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime() - 1);
                Vector3d plUp  = Vector3d.Cross(vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime()) - vessel.mainBody.referenceBody.getPositionAtUT(Planetarium.GetUniversalTime()), vessel.mainBody.getPositionAtUT(Planetarium.GetUniversalTime() + vessel.mainBody.orbit.period / 4) - vessel.mainBody.referenceBody.getPositionAtUT(Planetarium.GetUniversalTime() + vessel.mainBody.orbit.period / 4)).normalized;
                angleToPrograde = RTUtil.ClampDegrees360((((vessel.orbit.inclination > 90) || (vessel.orbit.inclination < -90)) ? 1 : -1) * ((Vector3)up).AngleInPlane(plUp, delta));
            }
            else
            {
                angleToPrograde = 0;
            }

            mainBody = vessel.mainBody;

            radius = (CoM - vessel.mainBody.position).magnitude;

            mass               = thrustAvailable = thrustMinimum = massDrag = torqueThrustPYAvailable = 0;
            torqueAvailable    = new Vector3d();
            rcsThrustAvailable = new Vector6();
            rcsTorqueAvailable = new Vector6();

            EngineInfo einfo = new EngineInfo(forward, CoM);
            IntakeInfo iinfo = new IntakeInfo();

            foreach (Part p in vessel.parts)
            {
                if (p.physicalSignificance != Part.PhysicalSignificance.NONE)
                {
                    double partMass = p.mass + p.GetResourceMass();
                    mass     += partMass;
                    massDrag += partMass * p.maximum_drag;
                }

                if (vessel.ActionGroups[KSPActionGroup.RCS])
                {
                    foreach (ModuleRCS pm in p.Modules.OfType <ModuleRCS>())
                    {
                        double   maxT         = pm.thrusterPower;
                        Vector3d partPosition = p.Rigidbody.worldCenterOfMass - CoM;

                        if ((pm.isEnabled) && (!pm.isJustForShow))
                        {
                            foreach (Transform t in pm.thrusterTransforms)
                            {
                                Vector3d thrusterThrust = -t.up * pm.thrusterPower;
                                rcsThrustAvailable.Add(thrusterThrust);
                                Vector3d thrusterTorque = vessel.GetTransform().InverseTransformDirection(Vector3.Cross(partPosition, thrusterThrust));
                                rcsTorqueAvailable.Add(thrusterTorque);
                            }
                        }
                    }
                }
                if (p is CommandPod)
                {
                    torqueAvailable += Vector3d.one * Math.Abs(((CommandPod)p).rotPower);
                }

                foreach (PartModule pm in p.Modules)
                {
                    if (!pm.isEnabled)
                    {
                        continue;
                    }

                    if (pm is ModuleReactionWheel)
                    {
                        ModuleReactionWheel rw = (ModuleReactionWheel)pm;
                        if (rw.wheelState == ModuleReactionWheel.WheelState.Active)
                        {
                            torqueAvailable += new Vector3d(rw.PitchTorque, rw.RollTorque, rw.YawTorque);
                        }
                    }
                    if (pm is ModuleEngines)
                    {
                        einfo.AddNewEngine(pm as ModuleEngines);
                    }
                    else if (pm is ModuleResourceIntake)
                    {
                        iinfo.addIntake(pm as ModuleResourceIntake);
                    }
                }
            }

            torqueAvailable += Vector3d.Max(rcsTorqueAvailable.positive, rcsTorqueAvailable.negative); // Should we use Max or Min ?

            thrustAvailable         += einfo.thrustAvailable;
            thrustMinimum           += einfo.thrustMinimum;
            torqueThrustPYAvailable += einfo.torqueThrustPYAvailable;

            // Convert the resource information from the einfo and iinfo format
            // to the more useful ResourceInfo format.
            resources = new Dictionary <int, ResourceInfo>();
            foreach (var info in einfo.resourceRequired)
            {
                int id  = info.Key;
                var req = info.Value;
                resources[id] = new ResourceInfo(
                    PartResourceLibrary.Instance.GetDefinition(id),
                    req.requiredLastFrame,
                    req.requiredAtMaxThrottle,
                    iinfo.getIntakes(id));
            }

            int intakeAirId = PartResourceLibrary.Instance.GetDefinition("IntakeAir").id;

            intakeAir       = 0;
            intakeAirNeeded = 0;
            intakeAirAtMax  = 0;
            if (resources.ContainsKey(intakeAirId))
            {
                intakeAir       = resources[intakeAirId].intakeProvided;
                intakeAirNeeded = resources[intakeAirId].required;
                intakeAirAtMax  = resources[intakeAirId].requiredAtMaxThrottle;
            }

            angularMomentum = new Vector3d(angularVelocity.x * MoI.x, angularVelocity.y * MoI.y, angularVelocity.z * MoI.z);

            maxThrustAccel = thrustAvailable / mass;
            minThrustAccel = thrustMinimum / mass;

            inertiaTensor = new Matrix3x3();
            foreach (Part p in vessel.parts)
            {
                if (p.Rigidbody == null)
                {
                    continue;
                }

                //Compute the contributions to the vessel inertia tensor due to the part inertia tensor
                Vector3d   principalMoments = p.Rigidbody.inertiaTensor;
                Quaternion princAxesRot     = Quaternion.Inverse(vessel.GetTransform().rotation) * p.transform.rotation * p.Rigidbody.inertiaTensorRotation;
                Quaternion invPrincAxesRot  = Quaternion.Inverse(princAxesRot);

                for (int i = 0; i < 3; i++)
                {
                    Vector3d iHat = Vector3d.zero;
                    iHat[i] = 1;
                    for (int j = 0; j < 3; j++)
                    {
                        Vector3d jHat = Vector3d.zero;
                        jHat[j]              = 1;
                        inertiaTensor[i, j] += Vector3d.Dot(iHat, princAxesRot * Vector3d.Scale(principalMoments, invPrincAxesRot * jHat));
                    }
                }

                //Compute the contributions to the vessel inertia tensor due to the part mass and position
                double  partMass     = p.mass + p.GetResourceMass();
                Vector3 partPosition = vessel.GetTransform().InverseTransformDirection(p.Rigidbody.worldCenterOfMass - CoM);

                for (int i = 0; i < 3; i++)
                {
                    inertiaTensor[i, i] += partMass * partPosition.sqrMagnitude;

                    for (int j = 0; j < 3; j++)
                    {
                        inertiaTensor[i, j] += -partMass * partPosition[i] * partPosition[j];
                    }
                }
            }

            MoI             = new Vector3d(inertiaTensor[0, 0], inertiaTensor[1, 1], inertiaTensor[2, 2]);
            angularMomentum = inertiaTensor * angularVelocity;
        }
예제 #28
0
 protected override void DI_Start(StartState state)
 {
     if (HighLogic.LoadedSceneIsFlight)
     {
         this.torqueModule = this.part.Modules.OfType<ModuleReactionWheel>().Single();
     }
 }
예제 #29
0
파일: KRnDGUI.cs 프로젝트: zer0Kerbal/KRnD
        // 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);
        }
예제 #30
0
파일: AJERotor.cs 프로젝트: nimaroth/AJE
 public override void OnStart(StartState state)
 {
     if (state == StartState.Editor)
         return;
     if (vessel == null)
         return;
     engine = new EngineWrapper(part);
     engine.IspMultiplier = IspMultiplier;
     engine.idle = idle;
     engine.useVelocityCurve = false;
     engine.ThrustUpperLimit = maxThrust;
     float omega = rpm * 0.1047f;
     //            power *= 745.7f;
     aje = new AJERotorSolver(omega, r, weight, power * 745.7f, 1.2f, VTOLbuff);
     sas = (ModuleReactionWheel)part.Modules["ModuleReactionWheel"];
     sasP = sas.PitchTorque;
     sasY = sas.YawTorque;
     sasR = sas.RollTorque;
 }
예제 #31
0
 public override void OnStart(StartState state)
 {
     base.OnStart(state);
     moduleSAS     = this.part.FindModuleImplementing <ModuleSAS>();
     reactionWheel = this.part.FindModuleImplementing <ModuleReactionWheel>();
 }
예제 #32
0
 public override void OnAwake()
 {
     SAS = part.FindModuleImplementing <ModuleReactionWheel>();
 }
예제 #33
0
 public static void DeactivateModule(this ModuleReactionWheel module)
 {
     module.State     = ModuleReactionWheel.WheelState.Disabled;
     module.isEnabled = false;
 }
예제 #34
0
 public static void ActivateModule(this ModuleReactionWheel module)
 {
     module.isEnabled = true;
     module.State     = ModuleReactionWheel.WheelState.Active;
 }
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
     module = base.part.FindModuleImplementing <ModuleReactionWheel>();
 }
 public override void OnAwake()
 {
     SAS = part.FindModuleImplementing<ModuleReactionWheel>();
 }
예제 #37
0
파일: KRnDGUI.cs 프로젝트: zer0Kerbal/KRnD
        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());
            }
        }
예제 #38
0
 void Apply(ModuleReactionWheel m, double k)
 {
   m.PitchTorque *= (float)k;
   m.YawTorque *= (float)k;
   m.RollTorque *= (float)k;
 }