Example #1
0
        public static Texture2D getHillshadingTile(CelestialBody body, int tileX, int tileY, int z, int size = 256)
        {
            if (body.pqsController == null)
                return null;
            size = getSize (body, size, z);
            TileData data = getTileData(body, tileX, tileY, z, size);
            size = data.size;
            Texture2D ret = new Texture2D (size, size, TextureFormat.ARGB32, false);
            for (int x = 0; x < size; x++) {
                for (int y = 0; y < size; y++) {
                    double s = Math.PI * 2 * body.Radius / ((size - 1) << z);
                    double dx = ((data.getEle(x-1, y-1) + 2*data.getEle(x, y-1) + data.getEle(x+1, y-1)) -
                        (data.getEle(x-1, y+1) + 2*data.getEle(x, y+1) + data.getEle(x+1, y+1))) /
                        (4.0 * s);
                    double dy = ((data.getEle(x-1, y-1) + 2*data.getEle(x-1, y) + data.getEle(x-1, y+1)) -
                        (data.getEle(x+1, y-1) + 2*data.getEle(x+1, y) + data.getEle(x+1, y+1))) /
                        (4.0 * s);

                    double slope = Math.PI / 2 - Math.Atan (Math.Sqrt (dx * dx + dy * dy));
                    double aspect = Math.Atan2 (dx, dy);

                    double cang = Math.Sin (Math.PI / 4) * Math.Sin (slope) +
                        Math.Cos (Math.PI / 4) * Math.Cos (slope) *
                        Math.Cos ((315) / 180 * Math.PI - Math.PI / 2 - aspect);
                    //Color c = (cang > 0.5)?(new Color(1f, 1f, 1f, (float)cang*2-1)):(new Color(0f, 0f, 0f, (float)cang*2));
                    Color c = new Color ((float)cang, (float)cang, (float)cang, 1.0f);
                    ret.SetPixel (x, y, c);
                }
            }
            ret.Apply ();
            return ret;
        }
        public static Vector3d DeltaVAndTimeForCheapestCourseCorrection(Orbit o, double UT, Orbit target, CelestialBody targetBody, double finalPeR, out double burnUT)
        {
            Vector3d collisionDV = DeltaVAndTimeForCheapestCourseCorrection(o, UT, target, out burnUT);
            Orbit collisionOrbit = o.PerturbedOrbit(burnUT, collisionDV);
            double collisionUT = collisionOrbit.NextClosestApproachTime(target, burnUT);
            Vector3d collisionPosition = target.SwappedAbsolutePositionAtUT(collisionUT);
            Vector3d collisionRelVel = collisionOrbit.SwappedOrbitalVelocityAtUT(collisionUT) - target.SwappedOrbitalVelocityAtUT(collisionUT);

            double soiEnterUT = collisionUT - targetBody.sphereOfInfluence / collisionRelVel.magnitude;
            Vector3d soiEnterRelVel = collisionOrbit.SwappedOrbitalVelocityAtUT(soiEnterUT) - target.SwappedOrbitalVelocityAtUT(soiEnterUT);

            double E = 0.5 * soiEnterRelVel.sqrMagnitude - targetBody.gravParameter / targetBody.sphereOfInfluence; //total orbital energy on SoI enter
            double finalPeSpeed = Math.Sqrt(2 * (E + targetBody.gravParameter / finalPeR)); //conservation of energy gives the orbital speed at finalPeR.
            double desiredImpactParameter = finalPeR * finalPeSpeed / soiEnterRelVel.magnitude; //conservation of angular momentum gives the required impact parameter

            Vector3d displacementDir = Vector3d.Cross(collisionRelVel, o.SwappedOrbitNormal()).normalized;
            Vector3d interceptTarget = collisionPosition + desiredImpactParameter * displacementDir;

            Vector3d velAfterBurn;
            Vector3d arrivalVel;
            LambertSolver.Solve(o.SwappedRelativePositionAtUT(burnUT), interceptTarget - o.referenceBody.position, collisionUT - burnUT, o.referenceBody, true, out velAfterBurn, out arrivalVel);

            Vector3d deltaV = velAfterBurn - o.SwappedOrbitalVelocityAtUT(burnUT);
            return deltaV;
        }
Example #3
0
        /// <summary>
        /// This function should return exactly the same value as Vessel.atmDensity, but is more generic because you don't need an actual vessel updated by KSP to get a value at the desired location.
        /// Computations are performed for the current body position, which means it's theoritically wrong if you want to know the temperature in the future, but since body rotation is not used (position is given in sun frame), you should get accurate results up to a few weeks.
        /// </summary>
        /// <param name="position"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static double GetTemperature(Vector3d position, CelestialBody body)
        {
            if (!body.atmosphere)
                return PhysicsGlobals.SpaceTemperature;

            double altitude = (position - body.position).magnitude - body.Radius;
            if (altitude > body.atmosphereDepth)
                return PhysicsGlobals.SpaceTemperature;

            Vector3 up = (position - body.position).normalized;
            float polarAngle = Mathf.Acos(Vector3.Dot(body.bodyTransform.up, up));
            if (polarAngle > Mathf.PI / 2.0f)
            {
                polarAngle = Mathf.PI - polarAngle;
            }
            float time = (Mathf.PI / 2.0f - polarAngle) * 57.29578f;

            Vector3 sunVector = (FlightGlobals.Bodies[0].position - position).normalized;
            float sunAxialDot = Vector3.Dot(sunVector, body.bodyTransform.up);
            float bodyPolarAngle = Mathf.Acos(Vector3.Dot(body.bodyTransform.up, up));
            float sunPolarAngle = Mathf.Acos(sunAxialDot);
            float sunBodyMaxDot = (1.0f + Mathf.Cos(sunPolarAngle - bodyPolarAngle)) * 0.5f;
            float sunBodyMinDot = (1.0f + Mathf.Cos(sunPolarAngle + bodyPolarAngle)) * 0.5f;
            float sunDotCorrected = (1.0f + Vector3.Dot(sunVector, Quaternion.AngleAxis(45f * Mathf.Sign((float)body.rotationPeriod), body.bodyTransform.up) * up)) * 0.5f;
            float sunDotNormalized = (sunDotCorrected - sunBodyMinDot) / (sunBodyMaxDot - sunBodyMinDot);
            double atmosphereTemperatureOffset = (double)body.latitudeTemperatureBiasCurve.Evaluate(time) + (double)body.latitudeTemperatureSunMultCurve.Evaluate(time) * sunDotNormalized + (double)body.axialTemperatureSunMultCurve.Evaluate(sunAxialDot);
            double temperature = body.GetTemperature(altitude) + (double)body.atmosphereTemperatureSunMultCurve.Evaluate((float)altitude) * atmosphereTemperatureOffset;

            return temperature;
        }
        public Overlay(string planet, float altitude, Material scaledMaterial, Material macroMaterial, Vector2 rotation, int layer, Transform celestialTransform, bool mainMenu, bool matchTerrain)
        {
            this.MainMenu = mainMenu;
            this.OverlayGameObject = new GameObject();
            this.Body = planet;
            this.Rotation = rotation;
            this.scaledMaterial = scaledMaterial;
            this.macroMaterial = macroMaterial;
            this.OriginalLayer = layer;
            this.celestialTransform = celestialTransform;
            this.altitude = altitude;
            this.matchTerrain = matchTerrain;

            CelestialBody[] celestialBodies = (CelestialBody[])CelestialBody.FindObjectsOfType(typeof(CelestialBody));
            celestialBody = celestialBodies.First(n => n.bodyName == this.Body);

            if (!mainMenu && matchTerrain)
            {
                IsoSphere.Create(OverlayGameObject, this.altitude, celestialBody);
            }
            else
            {
                IsoSphere.Create(OverlayGameObject, this.Radius, null);
            }

            var mr = OverlayGameObject.AddComponent<MeshRenderer>();
            mr.sharedMaterial = scaledMaterial;
            mr.castShadows = false;
            mr.receiveShadows = false;
            //mr.enabled = mainMenu;
            mr.enabled = true;
        }
Example #5
0
		protected override void Start()
		{
			//Initialize the map object
			Visible = SCANcontroller.controller.bigMapVisible;
			if (v == null)
				v = FlightGlobals.ActiveVessel;
			if (b == null)
				b = v.mainBody;
			if (bigmap == null)
			{
				bigmap = new SCANmap(b, true);
				bigmap.setProjection((MapProjection)SCANcontroller.controller.projection);
				bigmap.setWidth(SCANcontroller.controller.map_width);
			}
			WindowRect.x = SCANcontroller.controller.map_x;
			WindowRect.y = SCANcontroller.controller.map_y;
			currentColor = SCANcontroller.controller.colours == 0;
			lastColor = currentColor;
			lastResource = SCANcontroller.controller.map_ResourceOverlay;
			WindowCaption = string.Format("Map of {0}", b.theName);
			data = SCANUtil.getData(b);
			if (data == null)
			{
				data = new SCANdata(b);
				SCANcontroller.controller.addToBodyData(b, data);
			}
			bigmap.setBody(b);
			if (SCANconfigLoader.GlobalResource)
			{
				loadedResources = SCANcontroller.setLoadedResourceList();
			}
			TooltipsEnabled = SCANcontroller.controller.toolTips;
		}
		private static void DrawOrbit(Orbit o, CelestialBody referenceBody, Matrix4x4 screenTransform, int numSegments)
		{
			if (!o.activePatch) {
				return;
			}

			double startTA;
			double endTA;
			double now = Planetarium.GetUniversalTime();
			if (o.patchEndTransition != Orbit.PatchTransitionType.FINAL) {
				startTA = o.TrueAnomalyAtUT(o.StartUT);
				endTA = o.TrueAnomalyAtUT(o.EndUT);
				if (endTA < startTA) {
					endTA += 2.0 * Math.PI;
				}
			} else {
				startTA = o.GetUTforTrueAnomaly(0.0, now);
				endTA = startTA + 2.0 * Math.PI;
			}
			double dTheta = (endTA - startTA) / (double)numSegments;
			double theta = startTA;
			double timeAtTA = o.GetUTforTrueAnomaly(theta, now);
			Vector3 lastVertex = screenTransform.MultiplyPoint3x4(o.getRelativePositionFromTrueAnomaly(theta).xzy + (o.referenceBody.getTruePositionAtUT(timeAtTA)) - (referenceBody.getTruePositionAtUT(timeAtTA)));
			for (int i = 0; i < numSegments; ++i) {
				GL.Vertex3(lastVertex.x, lastVertex.y, 0.0f);
				theta += dTheta;
				timeAtTA = o.GetUTforTrueAnomaly(theta, now);

				Vector3 newVertex = screenTransform.MultiplyPoint3x4(o.getRelativePositionFromTrueAnomaly(theta).xzy + (o.referenceBody.getTruePositionAtUT(timeAtTA)) - (referenceBody.getTruePositionAtUT(timeAtTA)));
				GL.Vertex3(newVertex.x, newVertex.y, 0.0f);

				lastVertex = newVertex;
			}
		}
        public PowerUpDarkSide(Simulator simulator)
            : base(simulator)
        {
            Type = PowerUpType.DarkSide;
            Category = PowerUpCategory.Other;
            BuyImage = "darkside";
            BuyPrice = 500;
            BuyTitle = "Dark side (" + BuyPrice + "M$)";
            BuyDescription = "Enemies are hit by a mysterious force when they go behind a planet.";
            NeedInput = false;
            Position = Vector3.Zero;

            CorpsCeleste = new CelestialBody(
                    Simulation,
                    "",
                    Vector3.Zero,
                    Vector3.Zero,
                    0,
                    Size.Small,
                    float.MaxValue,
                    null,
                    0,
                    0,
                    false);
            CorpsCeleste.AttackPoints = 0.5f;

            SfxIn = "sfxDarkSide";
        }
Example #8
0
		protected override void Start()
		{
			Visible = SCANcontroller.controller.kscMapVisible;
			if (b == null)
				b = Planetarium.fetch.Home;
			if (bigmap == null)
			{
				bigmap = new SCANmap(b, true);
				bigmap.setProjection((MapProjection)SCANcontroller.controller.projection);
				bigmap.setWidth(720);
			}
			currentColor = SCANcontroller.controller.colours == 0;
			lastColor = currentColor;
			lastResource = SCANcontroller.controller.map_ResourceOverlay;
			WindowCaption = string.Format("Map of {0}", b.theName);
			data = SCANUtil.getData(b);
			if (data == null)
			{
				data = new SCANdata(b);
				SCANcontroller.controller.addToBodyData(b, data);
			}
			bigmap.setBody(b);
			if (SCANconfigLoader.GlobalResource)
			{
				loadedResources = SCANcontroller.setLoadedResourceList();
			}
			TooltipsEnabled = SCANcontroller.controller.toolTips;
		}
Example #9
0
        public static void DrawMapViewGroundMarker(CelestialBody body, double latitude, double longitude, Color c, double rotation = 0, double radius = 0)
        {
            Vector3d up = body.GetSurfaceNVector(latitude, longitude);
            var height = body.pqsController.GetSurfaceHeight(QuaternionD.AngleAxis(longitude, Vector3d.down) * QuaternionD.AngleAxis(latitude, Vector3d.forward) * Vector3d.right);
            if (height < body.Radius) { height = body.Radius; }
            Vector3d center = body.position + height * up;

            if (IsOccluded(center, body)) return;

            Vector3d north = Vector3d.Exclude(up, body.transform.up).normalized;

            if (radius <= 0) { radius = body.Radius / 15; }

            GLTriangleMap(new Vector3d[]{
                center,
                center + radius * (QuaternionD.AngleAxis(rotation - 10, up) * north),
                center + radius * (QuaternionD.AngleAxis(rotation + 10, up) * north)
            }, c);

            GLTriangleMap(new Vector3d[]{
                center,
                center + radius * (QuaternionD.AngleAxis(rotation + 110, up) * north),
                center + radius * (QuaternionD.AngleAxis(rotation + 130, up) * north)
            }, c);

            GLTriangleMap(new Vector3d[]{
                center,
                center + radius * (QuaternionD.AngleAxis(rotation - 110, up) * north),
                center + radius * (QuaternionD.AngleAxis(rotation - 130, up) * north)
            }, c);
        }
        public PerformOrbitalSurvey(string title,  CelestialBody targetBody)
            : base(title)
        {
            disableOnStateChange = true;

            this.targetBody = targetBody;
        }
		public progressBodyCollection(CelestialBodySubtree b)
		{
			body = b.Body;

			if (b.Body.isHomeWorld)
			{
				homeworld = true;
			}
			else
			{
				addProgressStandard(ProgressType.FLIGHT, b.Body, b.flight, progressParser.flightDescriptor, progressParser.StandardNote, progressParser.vesselNameFromNode(b.flight));
				addProgressStandard(ProgressType.SUBORBIT, b.Body, b.suborbit, progressParser.suborbitDescriptor, progressParser.StandardNote, progressParser.vesselNameFromNode(b.suborbit));
				addProgressStandard(ProgressType.FLYBY, b.Body, b.flyBy, progressParser.flybyDescriptor);
				addProgressStandard(ProgressType.FLYBYRETURN, b.Body, b.returnFromFlyby, progressParser.returnFlybyDescriptor, progressParser.RecoveryNote, progressParser.vesselNameFromNode(b.returnFromFlyby));
				addProgressStandard(ProgressType.LANDINGRETURN, b.Body, b.returnFromSurface, progressParser.returnLandingDescriptor, progressParser.RecoveryNote, progressParser.vesselNameFromNode(b.returnFromSurface));
			}

			addProgressStandard(ProgressType.ESCAPE, b.Body, b.escape, progressParser.escapeDescriptor);
			addProgressStandard(ProgressType.BASECONSTRUCTION, b.Body, b.baseConstruction, progressParser.baseDescriptor, progressParser.FacilityNote, progressParser.vesselNameFromNode(b.baseConstruction));
			addProgressStandard(ProgressType.CREWTRANSFER, b.Body, b.crewTransfer, progressParser.crewTransferDescriptor);
			addProgressStandard(ProgressType.DOCKING, b.Body, b.docking, progressParser.dockingDescriptor);
			addProgressStandard(ProgressType.FLAGPLANT, b.Body, b.flagPlant, progressParser.flagDescriptor);
			addProgressStandard(ProgressType.LANDING, b.Body, b.landing, progressParser.landingDescriptor, progressParser.StandardNote, progressParser.vesselNameFromNode(b.landing));
			addProgressStandard(ProgressType.ORBIT, b.Body, b.orbit, progressParser.orbitDescriptor, progressParser.StandardNote, progressParser.vesselNameFromNode(b.orbit));
			addProgressStandard(ProgressType.ORBITRETURN, b.Body, b.returnFromOrbit, progressParser.returnOrbitDescriptor, progressParser.RecoveryNote, progressParser.vesselNameFromNode(b.returnFromOrbit));
			addProgressStandard(ProgressType.RENDEZVOUS, b.Body, b.rendezvous, progressParser.rendezvousDescriptor);
			addProgressStandard(ProgressType.SCIENCE, b.Body, b.science, progressParser.scienceDescriptor, progressParser.StandardNote, progressParser.vesselNameFromNode(b.science));
			addProgressStandard(ProgressType.SPACEWALK, b.Body, b.spacewalk, progressParser.spacewalkDescriptor, progressParser.CrewNote, progressParser.crewNameFromNode(b.spacewalk));
			addProgressStandard(ProgressType.SPLASHDOWN, b.Body, b.splashdown, progressParser.splashdownDescriptor);
			addProgressStandard(ProgressType.STATIONCONSTRUCTION, b.Body, b.stationConstruction, progressParser.stationDescriptor, progressParser.FacilityNote, progressParser.vesselNameFromNode(b.stationConstruction));
			addProgressStandard(ProgressType.SURFACEEVA, b.Body, b.surfaceEVA, progressParser.EVADescriptor, progressParser.CrewNote, progressParser.crewNameFromNode(b.surfaceEVA));
		}
Example #12
0
		private void Startup()
		{
			//Initialize the map object
			Visible = false;
			if (HighLogic.LoadedSceneIsFlight)
			{
				v = SCANcontroller.controller.BigMap.V;
				b = SCANcontroller.controller.BigMap.Body;
				data = SCANcontroller.controller.BigMap.Data;
			}
			else if (HighLogic.LoadedSceneHasPlanetarium)
			{
				v = null;
				b = SCANcontroller.controller.kscMap.Body;
				data = SCANcontroller.controller.kscMap.Data;
			}
			if (spotmap == null)
			{
				spotmap = new SCANmap();
				spotmap.setSize(320, 240);
			}

			showOrbit = SCANcontroller.controller.map_orbit;
			showAnomaly = SCANcontroller.controller.map_markers;

			if (HighLogic.LoadedScene == GameScenes.SPACECENTER)
				showWaypoints = false;
			else
				showWaypoints = SCANcontroller.controller.map_waypoints;

			TooltipsEnabled = SCANcontroller.controller.toolTips;

			spotmap.setBody(b);
		}
Example #13
0
 public static Vector3 GetNorthVector(Vector3 position, CelestialBody body)
 {
     Vector3 geoPosA = VectorUtils.WorldPositionToGeoCoords(position, body);
     Vector3 geoPosB = new Vector3(geoPosA.x+1, geoPosA.y, geoPosA.z);
     Vector3 north = GetWorldSurfacePostion(geoPosB, body)-GetWorldSurfacePostion(geoPosA, body);
     return Vector3.ProjectOnPlane(north, body.GetSurfaceNVector(geoPosA.x, geoPosA.y)).normalized;
 }
Example #14
0
        protected override Vector3 UpdatePosition()
        {
            if (EditorLogic.RootPart == null) {
                /* DragCubes can get NaNed without this check */
                return Vector3.zero;
            }
            if (RCSBuildAid.Mode != PluginMode.Parachutes) {
                return Vector3.zero;
            }

            hasParachutes = RCSBuildAid.Parachutes.Count > 0;
            body = Settings.selected_body;
            altitude = MenuParachutes.altitude;
            temperature = body.GetTemperature (altitude);
            pressure = body.GetPressure (altitude);
            density = body.GetDensity (pressure, temperature);
            mach = (float)(speed / body.GetSpeedOfSound(pressure, density));
            gravity = body.gravity(altitude);

            findCenterOfDrag();
            speed = Vt = calculateTerminalVelocity ();
            /* unless I go at mach speeds I don't care about this
            reynolds = (float)(density * speed);
            reynoldsDragMult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate (reynolds);
            */
            dragForce.Vector = calculateDragForce ();

            return position;
        }
        public static VesselAerodynamicModel GetModel(Vessel ship, CelestialBody body)
        {
            foreach (var loadedAssembly in AssemblyLoader.loadedAssemblies)
            {
                try
                {
                    switch (loadedAssembly.name)
                    {
                        case "FerramAerospaceResearch":
                            var FARAPIType = loadedAssembly.assembly.GetType("FerramAerospaceResearch.FARAPI");

                                var FARAPI_CalculateVesselAeroForces = FARAPIType.GetMethodEx("CalculateVesselAeroForces", BindingFlags.Public | BindingFlags.Static, new Type[] { typeof(Vessel), typeof(Vector3).MakeByRefType(), typeof(Vector3).MakeByRefType(), typeof(Vector3), typeof(double) });

                            return new FARModel(ship, body, FARAPI_CalculateVesselAeroForces);

                        //case "MyModAssembly":
                        // implement here your atmo mod detection
                        // return new MyModModel(ship, body, any other parameter);
                    }
                }
                catch (Exception e)
                {
                    Debug.Log("Trajectories: failed to interface with assembly " + loadedAssembly.name);
                    Debug.Log("Using stock model instead");
                    Debug.Log(e.ToString());
                }
            }

            // Using stock model if no other aerodynamic is detected or if any error occured
            return new StockModel(ship, body);
        }
        //Computes the time until the phase angle between the launchpad and the target equals the given angle.
        //The convention used is that phase angle is the angle measured starting at the target and going east until
        //you get to the launchpad.
        //The time returned will not be exactly accurate unless the target is in an exactly circular orbit. However,
        //the time returned will go to exactly zero when the desired phase angle is reached.
        public static double TimeToPhaseAngle(double phaseAngle, CelestialBody launchBody, double launchLongitude, Orbit target)
        {
            double launchpadAngularRate = 360 / launchBody.rotationPeriod;
            double targetAngularRate = 360.0 / target.period;
            if (Vector3d.Dot(target.SwappedOrbitNormal(), launchBody.angularVelocity) < 0) targetAngularRate *= -1; //retrograde target

            Vector3d currentLaunchpadDirection = launchBody.GetSurfaceNVector(0, launchLongitude);
            Vector3d currentTargetDirection = target.SwappedRelativePositionAtUT(Planetarium.GetUniversalTime());
            currentTargetDirection = Vector3d.Exclude(launchBody.angularVelocity, currentTargetDirection);

            double currentPhaseAngle = Math.Abs(Vector3d.Angle(currentLaunchpadDirection, currentTargetDirection));
            if (Vector3d.Dot(Vector3d.Cross(currentTargetDirection, currentLaunchpadDirection), launchBody.angularVelocity) < 0)
            {
                currentPhaseAngle = 360 - currentPhaseAngle;
            }

            double phaseAngleRate = launchpadAngularRate - targetAngularRate;

            double phaseAngleDifference = MuUtils.ClampDegrees360(phaseAngle - currentPhaseAngle);

            if (phaseAngleRate < 0)
            {
                phaseAngleRate *= -1;
                phaseAngleDifference = 360 - phaseAngleDifference;
            }

            return phaseAngleDifference / phaseAngleRate;
        }
Example #17
0
 public static void Complex(OrbitDriver currentlyEditing, double inclination, double eccentricity,
     double semiMajorAxis, double longitudeAscendingNode, double argumentOfPeriapsis,
     double meanAnomalyAtEpoch, double epoch, CelestialBody body)
 {
     SetOrbit(currentlyEditing, CreateOrbit(inclination, eccentricity, semiMajorAxis,
         longitudeAscendingNode, argumentOfPeriapsis, meanAnomalyAtEpoch, epoch, body));
 }
 public static void GravParamToOthers(CelestialBody body)
 {
     double rsq = body.Radius * body.Radius;
     body.Mass = body.gravParameter * (1 / 6.674E-11);
     body.GeeASL = body.gravParameter / 9.81 / rsq;
     body.gMagnitudeAtCenter = body.gravParameter;
 }
        public bool isValidFor(Vessel vessel, CelestialBody body)
        {
            if (vessel != vessel_ || body_ != body)
                return false;

            if (Settings.fetch.AutoUpdateAerodynamicModel)
            {
                double newRefDrag = computeFARReferenceDrag();
                if (referenceDrag == 0)
                {
                    referenceDrag = newRefDrag;
                }
                double ratio = Math.Max(newRefDrag, referenceDrag) / Math.Max(1, Math.Min(newRefDrag, referenceDrag));
                if (ratio > 1.2 && DateTime.Now > nextAllowedAutomaticUpdate || referencePartCount != vessel.Parts.Count)
                {
                    nextAllowedAutomaticUpdate = DateTime.Now.AddSeconds(10); // limit updates frequency (could make the game almost unresponsive on some computers)
                    #if DEBUG
                    ScreenMessages.PostScreenMessage("Trajectory aerodynamic model auto-updated");
                    #endif
                    isValid = false;
                }
            }

            return isValid;
        }
Example #20
0
            public Vector3d velocity; // velocity in world frame relatively to the reference body

            public VesselState(Vessel vessel)
            {
                referenceBody = vessel.orbit.referenceBody;
                time = Planetarium.GetUniversalTime();
                position = vessel.GetWorldPos3D() - referenceBody.position;
                velocity = vessel.obt_velocity;
            }
Example #21
0
        public static void UpdateThermodynamicsPre(ModularFI.ModularFlightIntegrator fi)
        {
            if (fi.CurrentMainBody != body)
            {
                body = fi.CurrentMainBody;
                RealHeatUtils.baseTempCurve.CalculateNewAtmTempCurve(body, RealHeatUtils.debugging);
            }

            if (fi.staticPressurekPa > 0d)
            {
                float spd = (float)fi.spd;

                // set shock temperature
                fi.Vessel.externalTemperature = fi.externalTemperature = fi.atmosphericTemperature + (double)RealHeatUtils.baseTempCurve.EvaluateTempDiffCurve(spd);

                // get gamma
                double Cp = (double)RealHeatUtils.baseTempCurve.EvaluateVelCpCurve(spd);
                double R = (double)RealHeatUtils.baseTempCurve.specificGasConstant;
                double Cv = Cp - R;
                double gamma = Cp / Cv;

                // change density lerp
                double shockDensity = GetShockDensity(fi.density, fi.mach, gamma);
                fi.DensityThermalLerp = CalculateDensityThermalLerp(shockDensity);

                // reset background temps
                fi.backgroundRadiationTemp = CalculateBackgroundRadiationTemperature(fi.atmosphericTemperature, fi.DensityThermalLerp);
                fi.backgroundRadiationTempExposed = CalculateBackgroundRadiationTemperature(fi.externalTemperature * 2d, fi.DensityThermalLerp); // blunt bodies multiply BRT by 0.5, so multiply by 2 here.
                //print("At rho " + fi.density + "/" + shockDensity + ", gamma " + gamma + ", DTL " + fi.DensityThermalLerp + ", BT = " + fi.backgroundRadiationTempExposed.ToString("N2") + "/" + fi.backgroundRadiationTemp.ToString("N2"));
            }
        }
Example #22
0
 public static float getMaxAtmosphericAltitude(CelestialBody body) 
 {
     if (!body.atmosphere) return 0;
     
     //return (float)-body.atmosphereScaleHeight * 1000.0f * Mathf.Log(1e-6f);
     return (float)-body.atmosphereDepth * 1000.0f * Mathf.Log(1e-6f);
 }
 public LocationAndSituationParameter()
 {
     targetSituation = Vessel.Situations.ESCAPING;
     targetBody = null;
     noun = "potato";
     this.successCounter = 0;
 }
        public static double GetPressure(Vector3 position, CelestialBody body)
        {
            double latitude = body.GetLatitude(position) / 180.0 * Math.PI;
            double altitude = (position - body.position).magnitude - body.Radius;
            return GetPressure(altitude, latitude, body);

        }
Example #25
0
        private static Orbit CreateOrbit(double inc, double e, double sma, double lan, double w, double mEp, double epoch, CelestialBody body)
        {
            if (double.IsNaN(inc))
                inc = 0;
            if (double.IsNaN(e))
                e = 0;
            if (double.IsNaN(sma))
                sma = body.Radius + body.maxAtmosphereAltitude + 10000;
            if (double.IsNaN(lan))
                lan = 0;
            if (double.IsNaN(w))
                w = 0;
            if (double.IsNaN(mEp))
                mEp = 0;
            if (double.IsNaN(epoch))
                mEp = Planetarium.GetUniversalTime();

            if (Math.Sign(e - 1) == Math.Sign(sma))
                sma = -sma;

            if (Math.Sign(sma) >= 0)
            {
                while (mEp < 0)
                    mEp += Math.PI * 2;
                while (mEp > Math.PI * 2)
                    mEp -= Math.PI * 2;
            }

            return new Orbit(inc, e, sma, lan, w, mEp, epoch, body);
        }
Example #26
0
        void Start() {
            if ( !Target ) {
                var ship = GameObject.Find( "Ship" );
                if ( ship ) {
                    Target = ship.GetComponentInParent<CelestialBody>();
                }
            }
            _defaultTimeScale = SimulationControl.instance.TimeScale;
            if ( timeScaleButtons.Length == 3 ) {
                timeScaleButtons[0].interactable = false;
            }
            if ( !ShipControl ) {
                ShipControl = Target.GetComponent<ShipController>();
            }
            if ( !FuelSlider ) {
				Debug.Log("SpaceGravity2D.ShipGUI: fuel slider ref is null");
            } else {
                FuelSlider.maxValue = ShipControl.MaxFuel;
                FuelSlider.value = ShipControl.Fuel;
            }
            if ( MarkPrefab ) {
                _markApoapsis = Instantiate( MarkPrefab ) as Transform;
                _markApoapsis.name = "apoapsisMark";
                _markApoapsis.GetComponentInChildren<Text>().text = "A";
                _markPeriapsis = Instantiate( MarkPrefab ) as Transform;
                _markPeriapsis.name = "periapsisMark";
                _markPeriapsis.GetComponentInChildren<Text>().text = "P";
            }

        }
        double tauP; //normalized parabolic transfer time

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ThrottleControlledAvionics.LambertSolver"/> class.
        /// </summary>
        /// <param name="orb">Starting orbit.</param>
        /// <param name="destination">Destination radius-vector.</param>
        /// <param name="UT">Starting UT.</param>
        public LambertSolver(Orbit orb, Vector3d destination, double UT)
        {
            orbit = orb;
            body = orbit.referenceBody;
            StartUT = UT;
            mu = body.gravParameter;

            r1 = orb.getRelativePositionAtUT(UT);
            var h  = Vector3d.Cross(r1, destination);
            if(h.sqrMagnitude < 0.01) h = orb.GetOrbitNormal();
            c  = destination-r1;

            cm  = c.magnitude;
            var r1m = r1.magnitude;
            var r2m = destination.magnitude;
            var rrm = r1m+r2m;
            m  = rrm+cm;
            n  = rrm-cm;
            m3 = m*m*m;

            var transfer_angle = Vector3d.Angle(r1, destination)*Mathf.Deg2Rad;
            if(h.z < 0) transfer_angle = Utils.TwoPI-transfer_angle;
            sigma = Math.Sqrt(n/m);
            if(transfer_angle > Math.PI) sigma = -sigma;
            sigma2 = sigma*sigma;
            sigma3 = sigma2*sigma;
            sigma5 = sigma2*sigma3;

            tauP = 2/3.0*(1-sigma3);
            tauME = Math.Acos(sigma)+sigma*Math.Sqrt(1-sigma2);
        }
 public LocationAndSituationParameter(CelestialBody targetBody, Vessel.Situations targetSituation, string noun)
 {
     this.targetBody = targetBody;
     this.targetSituation = targetSituation;
     this.noun = noun;
     this.successCounter = 0;
 }
            public VesselData(VesselData vd)
            {
                name = vd.name;
                id = vd.id;
                craftURL = vd.craftURL;
                craftPart = vd.craftPart;
                flagURL = vd.flagURL;
                vesselType = vd.vesselType;
                body = vd.body;
                orbit = vd.orbit;
                latitude = vd.latitude;
                longitude = vd.longitude;
                altitude = vd.altitude;
                height = vd.height;
                orbiting = vd.orbiting;
                owned = vd.owned;
                pqsCity = vd.pqsCity;
                pqsOffset = vd.pqsOffset;
                heading = vd.heading;
                pitch = vd.pitch;
                roll = vd.roll;

                foreach (CrewData cd in vd.crew)
                {
                    crew.Add(new CrewData(cd));
                }
            }
 public CelestialBodyCoverageParameter(double coverage, CelestialBody targetBody, string title = null)
     : base(title)
 {
     this.coverage = coverage;
     this.targetBody = targetBody;
     disableOnStateChange = false;
 }
        public VesselHasVisited(CelestialBody destination, FlightLog.EntryType entryType, string title)
            : base(title)
        {
            if (title == null)
            {
                this.title = "Perform ";
                switch (entryType)
                {
                case FlightLog.EntryType.BoardVessel:
                    this.title = "Board a vessel on ";
                    break;

                case FlightLog.EntryType.Die:
                    this.title = "Die on ";
                    break;

                case FlightLog.EntryType.Escape:
                    this.title += "an escape from";
                    break;

                case FlightLog.EntryType.ExitVessel:
                    this.title = "Exit a vessel on ";
                    break;

                case FlightLog.EntryType.Flight:
                    this.title += "a flight on ";
                    break;

                case FlightLog.EntryType.Flyby:
                    this.title += "a flyby of ";
                    break;

                case FlightLog.EntryType.Land:
                    this.title += "a landing on ";
                    break;

                case FlightLog.EntryType.Launch:
                    this.title += "a launch from ";
                    break;

                case FlightLog.EntryType.Orbit:
                    this.title += "an orbit of ";
                    break;

                case FlightLog.EntryType.PlantFlag:
                    this.title = "Plant a flag on ";
                    break;

                case FlightLog.EntryType.Recover:
                    this.title += " a recovery on ";
                    break;

                case FlightLog.EntryType.Spawn:
                    this.title = "Spawn on ";
                    break;

                case FlightLog.EntryType.Suborbit:
                    this.title += "a sub-orbital trajectory of ";
                    break;
                }
                if (destination != null)
                {
                    this.title += destination.theName;
                }
                else
                {
                    this.title += "any body";
                }
            }
            else
            {
                this.title = title;
            }
            this.destination = destination;
            this.entryType   = entryType;
        }
Example #32
0
 public extern bool HasParent(CelestialBody body);
Example #33
0
 public extern bool HasChild(CelestialBody body);
        private int DrawTransferAngleButtons(KACAlarm tmpAlarm)
        {
            if ((tmpAlarm.TypeOfAlarm == KACAlarm.AlarmTypeEnum.Transfer || tmpAlarm.TypeOfAlarm == KACAlarm.AlarmTypeEnum.TransferModelled) &&
                (HighLogic.LoadedScene == GameScenes.TRACKSTATION || HighLogic.LoadedScene == GameScenes.FLIGHT))
            {
                //right type of alarm, now is the text there
                Match matchPhase      = Regex.Match(tmpAlarm.Notes, "(?<=Phase\\sAngle\\:\\s+)\\S+(?=°)");
                Match matchEjectPro   = Regex.Match(tmpAlarm.Notes, "(?<=Ejection\\sAngle\\:\\s+)\\S+(?=°\\sto\\sprograde)");
                Match matchEjectRetro = Regex.Match(tmpAlarm.Notes, "(?<=Ejection\\sAngle\\:\\s+)\\S+(?=°\\sto\\sretrograde)");
                if (matchPhase.Success && (matchEjectPro.Success || matchEjectRetro.Success))
                {
                    try
                    {
                        //LogFormatted_DebugOnly("{0}", matchPhase.Value);
                        Double dblPhase = Convert.ToDouble(matchPhase.Value);
                        Double dblEject;
                        if (matchEjectPro.Success)
                        {
                            dblEject = Convert.ToDouble(matchEjectPro.Value);
                        }
                        else
                        {
                            dblEject = Convert.ToDouble(matchEjectRetro.Value);
                        }

                        GUILayout.BeginHorizontal();

                        CelestialBody cbOrigin = FlightGlobals.Bodies.Single(b => b.bodyName == tmpAlarm.XferOriginBodyName);
                        CelestialBody cbTarget = FlightGlobals.Bodies.Single(b => b.bodyName == tmpAlarm.XferTargetBodyName);

                        GUIStyle styleAngleButton = new GUIStyle(KACResources.styleSmallButton)
                        {
                            fixedWidth = 180
                        };

                        if (DrawToggle(ref blnShowPhaseAngle, "Show Phase Angle", styleAngleButton))
                        {
                            if (blnShowPhaseAngle)
                            {
                                EjectAngle.HideAngle();
                                blnShowEjectAngle = false;
                                PhaseAngle.DrawAngle(cbOrigin, cbTarget, dblPhase);
                            }
                            else
                            {
                                PhaseAngle.HideAngle();
                            }
                        }
                        if (DrawToggle(ref blnShowEjectAngle, "Show Eject Angle", styleAngleButton))
                        {
                            if (blnShowEjectAngle)
                            {
                                PhaseAngle.HideAngle();
                                blnShowPhaseAngle = false;
                                EjectAngle.DrawAngle(cbOrigin, dblEject, matchEjectRetro.Success);
                            }
                            else
                            {
                                EjectAngle.HideAngle();
                            }
                        }
                        GUILayout.EndHorizontal();

                        //if (GUILayout.Toggle()) {

                        //}
                        //GUILayout.Label(String.Format("P:{0} - E:{1}",dblPhase,dblEject));

                        return(1);
                    }
                    catch (Exception)
                    {
                        GUILayout.Label("Unable to decipher TWP Phase and Eject Angle found in notes");
                        return(1);
                    }
                }
                else
                {
                    GUILayout.Label("No TWP Phase and Eject Angle found in notes");
                    return(1);
                }
            }
            else
            {
                return(0);
            }
        }
Example #35
0
            public RingLoader(CelestialBody body)
            {
                // Is this a spawned body?
                if (body?.scaledBody == null || Injector.IsInPrefab)
                {
                    throw new InvalidOperationException("The body must be already spawned by the PSystemManager.");
                }

                Value = new GameObject(body.transform.name + "Ring").AddComponent <Ring>();
                Value.transform.parent = body.scaledBody.transform;
                Value.planetRadius     = (Single)body.Radius;

                // Need to check the parent body's rotation to orient the LAN properly
                Value.referenceBody = body;

                // Create the Component callback
                Components = new CallbackList <ComponentLoader <Ring> > (e =>
                {
                    Value.Components = Components.Select(c => c.Value).ToList();
                });

                // Load existing Modules
                foreach (IComponent <Ring> component in Value.Components)
                {
                    Type componentType = component.GetType();
                    foreach (Type loaderType in Parser.ModTypes)
                    {
                        if (loaderType.BaseType == null)
                        {
                            continue;
                        }
                        if (loaderType.BaseType.Namespace != "Kopernicus.Configuration")
                        {
                            continue;
                        }
                        if (!loaderType.BaseType.Name.StartsWith("ComponentParser"))
                        {
                            continue;
                        }
                        if (loaderType.BaseType.GetGenericArguments()[0] != Value.GetType())
                        {
                            continue;
                        }
                        if (loaderType.BaseType.GetGenericArguments()[1] != componentType)
                        {
                            continue;
                        }

                        // We found our loader type
                        ComponentLoader <Ring> loader = (ComponentLoader <Ring>)Activator.CreateInstance(loaderType);
                        loader.Create(component);
                        Components.Add(loader);
                    }
                }
                if (Value.innerMultCurve == null)
                {
                    Value.innerMultCurve = new FloatCurve(new Keyframe[] { new Keyframe(0, 1), new Keyframe(1, 1) });
                }
                if (Value.outerMultCurve == null)
                {
                    Value.outerMultCurve = new FloatCurve(new Keyframe[] { new Keyframe(0, 1), new Keyframe(1, 1) });
                }
            }
Example #36
0
		public static void Body_info(this Panel p)
		{
			// only show in mapview
			if (!MapView.MapIsEnabled) return;

			// only show if there is a selected body and that body is not the sun
			CelestialBody body = Lib.SelectedBody();
			if (body == null || (body.flightGlobalsIndex == 0 && !Features.Radiation)) return;

			// shortcut
			CelestialBody sun = FlightGlobals.Bodies[0];

			// for all bodies except the sun
			if (body != sun)
			{
				// calculate simulation values
				double atmo_factor = Sim.AtmosphereFactor(body, 0.7071);
				double gamma_factor = Sim.GammaTransparency(body, 0.0);
				double sun_dist = Sim.Apoapsis(Lib.PlanetarySystem(body)) - sun.Radius - body.Radius;
				Vector3d sun_dir = (sun.position - body.position).normalized;
				double solar_flux = Sim.SolarFlux(sun_dist) * atmo_factor;
				double albedo_flux = Sim.AlbedoFlux(body, body.position + sun_dir * body.Radius);
				double body_flux = Sim.BodyFlux(body, 0.0);
				double total_flux = solar_flux + albedo_flux + body_flux + Sim.BackgroundFlux();
				double temperature = body.atmosphere ? body.GetTemperature(0.0) : Sim.BlackBodyTemperature(total_flux);

				// calculate night-side temperature
				double total_flux_min = Sim.AlbedoFlux(body, body.position - sun_dir * body.Radius) + body_flux + Sim.BackgroundFlux();
				double temperature_min = Sim.BlackBodyTemperature(total_flux_min);

				// calculate radiation at body surface
				double radiation = Radiation.ComputeSurface(body, gamma_factor);

				// surface panel
				string temperature_str = body.atmosphere
				  ? Lib.HumanReadableTemp(temperature)
				  : Lib.BuildString(Lib.HumanReadableTemp(temperature_min), " / ", Lib.HumanReadableTemp(temperature));
				p.AddSection("SURFACE");
				p.AddContent("temperature", temperature_str);
				p.AddContent("solar flux", Lib.HumanReadableFlux(solar_flux));
				if (Features.Radiation) p.AddContent("radiation", Lib.HumanReadableRadiation(radiation));

				// atmosphere panel
				if (body.atmosphere)
				{
					p.AddSection("ATMOSPHERE");
					p.AddContent("breathable", Sim.Breathable(body) ? "yes" : "no");
					p.AddContent("light absorption", Lib.HumanReadablePerc(1.0 - Sim.AtmosphereFactor(body, 0.7071)));
					if (Features.Radiation) p.AddContent("gamma absorption", Lib.HumanReadablePerc(1.0 - Sim.GammaTransparency(body, 0.0)));
				}
			}

			// rendering panel
			if (Features.Radiation)
			{
				p.AddSection("RENDERING");
				p.AddContent("inner belt", Radiation.show_inner ? "<color=green>show</color>" : "<color=red>hide</color>", string.Empty, () => p.Toggle(ref Radiation.show_inner));
				p.AddContent("outer belt", Radiation.show_outer ? "<color=green>show</color>" : "<color=red>hide</color>", string.Empty, () => p.Toggle(ref Radiation.show_outer));
				p.AddContent("magnetopause", Radiation.show_pause ? "<color=green>show</color>" : "<color=red>hide</color>", string.Empty, () => p.Toggle(ref Radiation.show_pause));
			}

			// explain the user how to toggle the BodyInfo window
			p.AddContent(string.Empty);
			p.AddContent("<i>Press <b>B</b> to open this window again</i>");

			// set metadata
			p.Title(Lib.BuildString(Lib.Ellipsis(body.bodyName, Styles.ScaleStringLength(24)), " <color=#cccccc>BODY INFO</color>"));
		}
        public static T ParseSingleValue <T>(string key, string stringValue, bool allowExpression)
        {
            ExpressionParser <T> parser;
            T value;

            // Handle nullable
            if (typeof(T).Name == "Nullable`1")
            {
                if (typeof(T).GetGenericArguments()[0].IsEnum)
                {
                    value = (T)Enum.Parse(typeof(T).GetGenericArguments()[0], stringValue, true);
                }
                else
                {
                    value = (T)Convert.ChangeType(stringValue, typeof(T).GetGenericArguments()[0]);
                }
            }
            else if (allowExpression && (parser = BaseParser.GetParser <T>()) != null)
            {
                if (initialLoad)
                {
                    value = parser.ParseExpression(key, stringValue, currentDataNode);
                }
                else
                {
                    value = parser.ExecuteExpression(key, stringValue, currentDataNode);
                }
            }
            // Enum parsing logic
            else if (typeof(T).IsEnum)
            {
                value = (T)Enum.Parse(typeof(T), stringValue, true);
            }
            else if (typeof(T) == typeof(AvailablePart))
            {
                value = (T)(object)ParsePartValue(stringValue);
            }
            else if (typeof(T) == typeof(ContractGroup))
            {
                if (!ContractGroup.contractGroups.ContainsKey(stringValue))
                {
                    throw new ArgumentException("No contract group with name '" + stringValue + "'");
                }
                value = (T)(object)ContractGroup.contractGroups[stringValue];
            }
            else if (typeof(T) == typeof(CelestialBody))
            {
                value = (T)(object)ParseCelestialBodyValue(stringValue);
            }
            else if (typeof(T) == typeof(PartResourceDefinition))
            {
                value = (T)(object)ParseResourceValue(stringValue);
            }
            else if (typeof(T) == typeof(Resource))
            {
                value = (T)(object)new Resource(ParseResourceValue(stringValue));
            }
            else if (typeof(T) == typeof(Agent))
            {
                value = (T)(object)ParseAgentValue(stringValue);
            }
            else if (typeof(T) == typeof(Duration))
            {
                value = (T)(object)new Duration(DurationUtil.ParseDuration(stringValue));
            }
            else if (typeof(T) == typeof(ProtoCrewMember))
            {
                value = (T)(object)ParseProtoCrewMemberValue(stringValue);
            }
            else if (typeof(T) == typeof(Kerbal))
            {
                value = (T)(object)new Kerbal(stringValue);
            }
            else if (typeof(T) == typeof(Guid))
            {
                value = (T)(object)new Guid(stringValue);
            }
            else if (typeof(T) == typeof(Vessel))
            {
                value = (T)(object)ParseVesselValue(stringValue);
            }
            else if (typeof(T) == typeof(VesselIdentifier))
            {
                value = (T)(object)new VesselIdentifier(stringValue);
            }
            else if (typeof(T) == typeof(Vector3))
            {
                string[] vals = stringValue.Split(new char[] { ',' });
                float    x    = (float)Convert.ChangeType(vals[0], typeof(float));
                float    y    = (float)Convert.ChangeType(vals[1], typeof(float));
                float    z    = (float)Convert.ChangeType(vals[2], typeof(float));
                value = (T)(object)new Vector3(x, y, z);
            }
            else if (typeof(T) == typeof(Vector3d))
            {
                string[] vals = stringValue.Split(new char[] { ',' });
                double   x    = (double)Convert.ChangeType(vals[0], typeof(double));
                double   y    = (double)Convert.ChangeType(vals[1], typeof(double));
                double   z    = (double)Convert.ChangeType(vals[2], typeof(double));
                value = (T)(object)new Vector3d(x, y, z);
            }
            else if (typeof(T) == typeof(Type))
            {
                value = (T)(object)ParseTypeValue(stringValue);
            }
            else if (typeof(T) == typeof(ScienceSubject))
            {
                value = (T)(object)(ResearchAndDevelopment.Instance != null ? ResearchAndDevelopment.GetSubjectByID(stringValue) : null);
            }
            else if (typeof(T) == typeof(ScienceExperiment))
            {
                value = (T)(object)(ResearchAndDevelopment.Instance != null ? ResearchAndDevelopment.GetExperiment(stringValue) : null);
            }
            else if (typeof(T) == typeof(Color))
            {
                if ((stringValue.Length != 7 && stringValue.Length != 9) || stringValue[0] != '#')
                {
                    throw new ArgumentException("Invalid color code '" + stringValue + "': Must be # followed by 6 or 8 hex digits (ARGB or RGB).");
                }
                stringValue = stringValue.Replace("#", "");
                int a = 255;
                if (stringValue.Length == 8)
                {
                    a           = byte.Parse(stringValue.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
                    stringValue = stringValue.Substring(2, 6);
                }
                int r = byte.Parse(stringValue.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
                int g = byte.Parse(stringValue.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
                int b = byte.Parse(stringValue.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);

                value = (T)(object)(new Color(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f));
            }
            else if (typeof(T) == typeof(Biome))
            {
                string[]      biomeData = stringValue.Split(new char[] { ';' });
                CelestialBody cb        = ParseCelestialBodyValue(biomeData[0]);
                value = (T)(object)(new Biome(cb, biomeData[1]));
            }
            else if (typeof(T) == typeof(LaunchSite))
            {
                value = (T)(object)ParseLaunchSiteValue(stringValue);
            }
            // Do newline conversions
            else if (typeof(T) == typeof(string))
            {
                value = (T)(object)stringValue.Replace("&br;", "\n").Replace("\\n", "\n");
            }
            // Try a basic type
            else
            {
                value = (T)Convert.ChangeType(stringValue, typeof(T));
            }

            return(value);
        }
 public static bool CalculatePatch(Orbit p, Orbit nextPatch, double startEpoch, PatchedConics.SolverParameters pars, CelestialBody targetBody);
Example #39
0
 /// <summary>
 /// Updates this orbit to reflect the orbit that will be taken around the given body by an object with the
 /// given position and velocity at the given universal time.
 /// </summary>
 /// <param name="pos">The initial position of the object RELATIVE TO refBody at UT (YZ flipped)</param>
 /// <param name="vel">The initial velocity of the object (YZ flipped)</param>
 /// <param name="refBody">The main body</param>
 /// <param name="UT">The universal time at which to start the orbit.</param>
 public extern void UpdateFromStateVectors(Vector3d pos, Vector3d vel, CelestialBody refBody, double UT);
Example #40
0
        //public void OnDisable()
        //{
        //    //this.vessel.OnPostAutopilotUpdate -= ctrlState;
        //}

        //public void ctrlState(FlightCtrlState fc)
        //{
        //    if(TWR1Engaged && !TWR1HCOrbitDrop && TWR1Vessel != FlightGlobals.ActiveVessel)
        //    {
        //        print("throttl " + TWR1ThrustUp);
        //        fc.mainThrottle = (float)TWR1ThrustUp;
        //        //fc.mainThrottle = .99f;
        //    }
        //}


        public void FixedUpdate() //forum says "all physics calculations should be on FixedUpdate, not Update". not sure a throttle adjustment qualifies as a physics calc, but put it here anyway
        {
            //WarezCrawler 20180415
            //Don't do calculations when not needed
            if (!TWR1.TWR1Show)
            {
                return;
            }
            //string //errLine = "1";
            try
            {
                if (HighLogic.LoadedSceneIsFlight)
                {
                    //errLine = "2";
                    TWR1VelocityCurrent = (float)this.vessel.verticalSpeed; //set our current vertical velocity
                    //errLine = "3";
                    if (this.vessel.mainBody.ocean)
                    {
                        //errLine = "4";
                        TWR1HCToGround = Math.Min(this.vessel.altitude - this.vessel.pqsAltitude, this.vessel.altitude);
                    }
                    else
                    {
                        //errLine = "5";
                        TWR1HCToGround = this.vessel.altitude - this.vessel.pqsAltitude;
                    }
                    //errLine = "6";
                    TWR1Mass = this.vessel.GetTotalMass();
                    //errLine = "7";
                    TWR1SOI = this.vessel.mainBody;
                    //errLine = "8";
                    TWR1CoM = this.vessel.GetWorldPos3D(); //add exception here for destoryed parts
                    //errLine = "9";
                    TWR1Up = (TWR1CoM - this.vessel.mainBody.position).normalized;
                    //errLine = "10";
                    TWR1GravHeight = (float)this.vessel.altitude + (float)TWR1SOI.Radius;                   //gravity force at this altitude (not in m/s^2)
                    //errLine = "11";
                    TWR1GravForce = (float)TWR1SOI.gMagnitudeAtCenter / (float)Math.Pow(TWR1GravHeight, 2); //accel down due to gravity in m/s^2
                    //errLine = "12";
                    TWR1MaxThrust         = 0f;                                                             //maxthrust reset
                    TWR1MinThrust         = 0f;                                                             //minthrust reset
                    TWR1MaxThrustVertical = 0f;
                    TWR1MinThrustVertical = 0f;
                    actualThrustLastFrame = 0f;              //thrust dif reset
                    //errLine = "13";
                    foreach (Part part in this.vessel.Parts) //go through each part on vessel
                    {
                        //errLine = "14";
                        if (part.Modules.Contains("ModuleEngines") | part.Modules.Contains("ModuleEnginesFX")) //is part an engine?
                        {
                            float DavonThrottleID = 0;
                            if (part.Modules.Contains("DifferentialThrustEngineModule")) //Devon Throttle Control Installed?
                            {
                                foreach (PartModule pm in part.Modules)
                                {
                                    if (pm.moduleName == "DifferentialThrustEngineModule")
                                    {
                                        DavonThrottleID = (float)pm.Fields.GetValue("throttleFloatSelect"); //which throttle is engine assigned to?
                                    }
                                }
                            }
                            //errLine = "15";
                            if (DavonThrottleID == 0f)
                            {
                                foreach (PartModule TWR1PartModule in part.Modules) //change from part to partmodules
                                {
                                    //errLine = "16";
                                    if (TWR1PartModule.moduleName == "ModuleEngines") //find partmodule engine on th epart
                                    {
                                        //errLine = "16a";
                                        TWR1EngineModule = (ModuleEngines)TWR1PartModule; //change from partmodules to moduleengines
                                        // print("xform "+ TWR1EngineModule.thrustTransforms.Count + "||" + Vector3.Angle(TWR1EngineModule.thrustTransforms[0].forward,-TWR1Up));
                                        //print("TWR1 angle off" + Vector3.Angle(TWR1EngineModule.thrustTransforms[0].forward, TWR1Up));

                                        double offsetMultiplier;
                                        try
                                        {
                                            offsetMultiplier = Math.Max(0, Math.Cos(Mathf.Deg2Rad * Vector3.Angle(TWR1EngineModule.thrustTransforms[0].forward, -TWR1Up)));
                                            //Debug.Log("TWR1off:" + offsetMultiplier + ":" + TWR1EngineModule.thrustTransforms[0].forward + ":" + -TWR1Up);
                                        }
                                        catch
                                        {
                                            offsetMultiplier = 1;
                                        }
                                        //errLine = "16b";
                                        //how far off vertical is this engine?
                                        //print("of " + offsetMultiplier);
                                        if ((bool)TWR1PartModule.Fields.GetValue("throttleLocked") && TWR1EngineModule.isOperational)//if throttlelocked is true, this is solid rocket booster. then check engine is operational. if the engine is flamedout, disabled via-right click or not yet activated via stage control, isOperational returns false
                                        {
                                            //errLine = "16c";
                                            //Debug.Log("locked " + TWR1EngineModule.finalThrust);
                                            TWR1MaxThrust         += (double)((TWR1EngineModule.finalThrust) * offsetMultiplier); //add engine thrust to MaxThrust
                                            TWR1MaxThrustVertical += (double)(TWR1EngineModule.finalThrust);
                                            TWR1MinThrust         += (double)((TWR1EngineModule.finalThrust) * offsetMultiplier); //add engine thrust to MinThrust since this is an SRB
                                            TWR1MinThrustVertical += (double)(TWR1EngineModule.finalThrust);
                                        }
                                        else if (TWR1EngineModule.isOperational)//we know it is an engine and not a solid rocket booster so:
                                        {
                                            //errLine = "16d";
                                            //ModuleEngines engTest = (ModuleEngines)TWR1PartModule;
                                            //Debug.Log("twr1test " + TWR1EngineModule.thrustPercentage + ":" + TWR1EngineModule.maxFuelFlow * TWR1EngineModule.g * TWR1EngineModule.atmosphereCurve.Evaluate((float)(TWR1EngineModule.vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres)));
                                            //Debug.Log("twr1test " + TWR1EngineModule.finalThrust / TWR1EngineModule.currentThrottle + ":" + TWR1EngineModule.maxFuelFlow + ":" + TWR1EngineModule.g + ":" + TWR1EngineModule.atmosphereCurve.Evaluate(1f) + ":" + TWR1EngineModule.vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres );
                                            TWR1MaxThrust += (double)((TWR1EngineModule.maxFuelFlow * TWR1EngineModule.g * TWR1EngineModule.atmosphereCurve.Evaluate((float)(TWR1EngineModule.vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres)) * TWR1EngineModule.thrustPercentage / 100F) * offsetMultiplier); //add engine thrust to MaxThrust
                                            //errLine = "16d1";
                                            TWR1MaxThrustVertical += (double)((TWR1EngineModule.maxFuelFlow * TWR1EngineModule.g * TWR1EngineModule.atmosphereCurve.Evaluate((float)(TWR1EngineModule.vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres)) * TWR1EngineModule.thrustPercentage / 100F));
                                            //errLine = "16d2";
                                            //TWR1MinThrust += (double)((TWR1EngineModule.minThrust * TWR1EngineModule.thrustPercentage / 100F) * offsetMultiplier); //add engine thrust to MinThrust, stock engines all have min thrust of zero, but mods may not be 0
                                            //errLine = "16d3";
                                            //TWR1MinThrustVertical += (double)((TWR1EngineModule.minThrust * TWR1EngineModule.thrustPercentage / 100F));
                                            //errLine = "16d4";
                                        }
                                        //errLine = "16e";
                                        actualThrustLastFrame += (float)TWR1EngineModule.finalThrust * (float)offsetMultiplier;
                                    }
                                    else if (TWR1PartModule.moduleName == "ModuleEnginesFX") //find partmodule engine on th epart
                                    {
                                        //errLine = "17";
                                        TWR1EngineModuleFX = (ModuleEnginesFX)TWR1PartModule; //change from partmodules to moduleengines
                                        //errLine = "17a";
                                        double offsetMultiplier;
                                        try
                                        {
                                            //errLine = "17b";
                                            //Debug.Log("thturs " + TWR1EngineModuleFX.thrustTransforms.Count);

                                            offsetMultiplier = Math.Cos(Mathf.Deg2Rad * Vector3.Angle(TWR1EngineModuleFX.thrustTransforms[0].forward, -TWR1ControlUp)); //how far off vertical is this engine?
                                        }
                                        catch
                                        {
                                            offsetMultiplier = 1;
                                        }
                                        //errLine = "17c";
                                        if ((bool)TWR1PartModule.Fields.GetValue("throttleLocked") && TWR1EngineModuleFX.isOperational)//if throttlelocked is true, this is solid rocket booster. then check engine is operational. if the engine is flamedout, disabled via-right click or not yet activated via stage control, isOperational returns false
                                        {
                                            //errLine = "17d";
                                            TWR1MaxThrust         += (double)((TWR1EngineModuleFX.finalThrust) * offsetMultiplier); //add engine thrust to MaxThrust
                                            TWR1MaxThrustVertical += (double)((TWR1EngineModuleFX.finalThrust));
                                            TWR1MinThrust         += (double)((TWR1EngineModuleFX.finalThrust) * offsetMultiplier); //add engine thrust to MinThrust since this is an SRB
                                            TWR1MinThrustVertical += (double)((TWR1EngineModuleFX.finalThrust));
                                        }
                                        else if (TWR1EngineModuleFX.isOperational)//we know it is an engine and not a solid rocket booster so:
                                        {
                                            //errLine = "17e";
                                            TWR1MaxThrust += (double)((TWR1EngineModuleFX.maxFuelFlow * TWR1EngineModuleFX.g * TWR1EngineModuleFX.atmosphereCurve.Evaluate((float)(TWR1EngineModuleFX.vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres)) * TWR1EngineModuleFX.thrustPercentage / 100F) * offsetMultiplier); //add engine thrust to MaxThrust
                                            //errLine = "17e1";
                                            TWR1MaxThrustVertical += (double)((TWR1EngineModuleFX.maxFuelFlow * TWR1EngineModuleFX.g * TWR1EngineModuleFX.atmosphereCurve.Evaluate((float)(TWR1EngineModuleFX.vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres)) * TWR1EngineModuleFX.thrustPercentage / 100F));
                                            //errLine = "17e2";
                                            //TWR1MinThrust += (double)((TWR1EngineModuleFX.minThrust * TWR1EngineModuleFX.thrustPercentage / 100F) * offsetMultiplier); //add engine thrust to MinThrust, stock engines all have min thrust of zero, but mods may not be 0
                                            //errLine = "17e3";
                                            //TWR1MinThrustVertical += (double)((TWR1EngineModuleFX.minThrust * TWR1EngineModuleFX.thrustPercentage / 100F));
                                            //errLine = "17e4";
                                        }
                                        //errLine = "17f";
                                        actualThrustLastFrame += (float)TWR1EngineModuleFX.finalThrust * (float)offsetMultiplier;
                                    }
                                }
                            }
                        }
                    }
                    //errLine = "18";
                    TWR1HC5Thrust = (Math.Max((TWR1MaxThrustVertical * .05), TWR1MinThrustVertical) / TWR1Mass) - TWR1GravForce; //accel at 5% thrust, makes sure engine is on to allow for ship horizontal speed adjustment. this outside HC method for UI dispaly
                    TWR1HC1Thrust = (Math.Max((TWR1MaxThrustVertical * .01), TWR1MinThrustVertical) / TWR1Mass) - TWR1GravForce;
                    //errLine = "19";
                    //Debug.Log("startofit " + TWR1GravForce + "||" + TWR1Mass + "||" + TWR1MaxThrust);
                    TWR1HC80Thrust = ((TWR1MaxThrustVertical * .8f) / TWR1Mass) - TWR1GravForce; //use 80% acceleration to account for being off vertical, planet grav reduces accel in this case this outside HC method for UI disaply
                    //Debug.Log(TWR1MaxThrust + " " + TWR1MinThrust + " " + TWR1HC80Thrust);
                    //errLine = "20";
                    if (!TWR1Engaged)
                    {
                        TWR1HeightCtrl = false;
                    }                                             //mod has been disengegaed, disengage height control
                    //errLine = "21";
                    if (!TWR1HeightCtrl)
                    {
                        TWR1HCOrbitDrop = false; //Height control not engaged, we can not be doing an OrbitDrop
                    }
                    //errLine = "22";
                    TWR1ControlUp = SetDirection(controlDirection, this.vessel);
                    //errLine = "23";
                    TWR1OrbitDropTimeNeeded = Math.Abs(Math.Min(0, TWR1VelocityCurrent)) / Math.Abs(TWR1HC80Thrust); //how much time is needed to orbit drop? if we are positive velocity, need zero time
                    //errLine = "24";
                    //altitude needed to orbit drop, is time to stop our current velocity of zero or lower (use zero if moving upwards) plus 20 seconds of falling due to gravity
                    //TWR1OrbitDropHeightNeeded = (Math.Abs(TWR1VelocityCurrent) * 40) + (TWR1HC80Thrust * Math.Pow(TWR1OrbitDropTimeNeeded, 2)) / 2; //how much altitude is needed to orbit drop?
                    TWR1OrbitDropHeightNeeded = (Math.Pow(((Math.Abs(Math.Min(TWR1VelocityCurrent, 0))) + TWR1GravForce * 20), 2) / (2 * TWR1HC80Thrust)) + (TWR1GravForce * 200) + (Math.Abs(Math.Min(TWR1VelocityCurrent, 0)) * 20); //twr1gravforce * 200 is shortcut for D = (accel * time^2) /2
                    //errLine = "25";
                    //Debug.Log("heightneed " + TWR1OrbitDropHeightNeeded + "||" + TWR1VelocityCurrent + "||" + TWR1GravForce + "||" + TWR1HC80Thrust);
                    TWR1HCDistToTarget = Math.Abs(TWR1HCToGround - TWR1HCTarget);
                    //errLine = "26";
                    TWR1ThrottleRead = this.vessel.ctrlState.mainThrottle;

                    //errLine = "27";

                    TWR1OffsetVert = Vector3.Angle(TWR1Up, TWR1ControlUp);
                    //Debug.Log("tip " + TWR1OffsetVert);

                    TWR1VesselPitch = Math.Max((90 - TWR1OffsetVert), 0);
                    //errLine = "28";
                    TWR1OffsetVertRadian = Mathf.Deg2Rad * TWR1OffsetVert;    //mathf.cos takes radians, not degrees, ask unity why
                    //errLine = "29";
                    TWR1OffsetVertRatio = Math.Cos(TWR1OffsetVertRadian);     //our compensation factor for being offset from vertical
                    //errLine = "30";
                    TWR1HCDistance = Math.Abs(TWR1HCToGround - TWR1HCTarget); //absolute distance to target altitude
                    //errLine = "31";
                    if (TWR1Engaged)
                    {
                        //errLine = "32";
                        TWR1Math();
                    }
                    //errLine = "33";
                }
            }

            catch (Exception e)
            {
                //Debug.Log("TWR1 Fixed Fail: " + //errLine + " " + e);
                Debug.Log("TWR1 Fixed Fail: " + e);
            }
        }
Example #41
0
 public extern Vector3d GetRotFrameVel(CelestialBody refBody);
Example #42
0
 public Streams(Connection conn, Service sc, CelestialBody body)
 {
     Init(conn, sc, body);
 }
Example #43
0
        public void Apply()
        {
            if (HighLogic.LoadedScene == GameScenes.LOADING)
            {
                return;
            }
            //Get updating player
            string updatePlayer = LockSystem.fetch.LockExists(vesselID) ? LockSystem.fetch.LockOwner(vesselID) : "Unknown";

            //Ignore updates to our own vessel if we are in flight and we aren't spectating
            if (!VesselWorker.fetch.isSpectating && (FlightGlobals.fetch.activeVessel != null ? FlightGlobals.fetch.activeVessel.id.ToString() == vesselID : false) && HighLogic.LoadedScene == GameScenes.FLIGHT)
            {
                DarkLog.Debug("ApplyVesselUpdate - Ignoring update for active vessel from " + updatePlayer);
                return;
            }
            Vessel updateVessel = FlightGlobals.fetch.vessels.FindLast(v => v.id.ToString() == vesselID);

            if (updateVessel == null)
            {
                //DarkLog.Debug("ApplyVesselUpdate - Got vessel update for " + vesselID + " but vessel does not exist");
                return;
            }
            CelestialBody updateBody = FlightGlobals.Bodies.Find(b => b.bodyName == bodyName);

            if (updateBody == null)
            {
                DarkLog.Debug("ApplyVesselUpdate - updateBody not found");
                return;
            }

            //Rotation
            Quaternion updateRotation = new Quaternion(rotation[0], rotation[1], rotation[2], rotation[3]);

            updateVessel.SetRotation(updateVessel.mainBody.bodyTransform.rotation * updateRotation);
            if (updateVessel.packed)
            {
                updateVessel.srfRelRotation       = updateRotation;
                updateVessel.protoVessel.rotation = updateVessel.srfRelRotation;
            }


            //Position/Velocity
            if (isSurfaceUpdate)
            {
                //Get the new position/velocity
                Vector3d updatePostion      = updateBody.GetWorldSurfacePosition(position[0], position[1], position[2]);
                Vector3d updateVelocity     = updateBody.bodyTransform.rotation * new Vector3d(velocity[0], velocity[1], velocity[2]);
                Vector3d updateAcceleration = updateBody.bodyTransform.rotation * new Vector3d(acceleration[0], acceleration[1], acceleration[2]);
                if (updateVessel.packed)
                {
                    updateVessel.latitude              = position[0];
                    updateVessel.longitude             = position[1];
                    updateVessel.altitude              = position[2];
                    updateVessel.protoVessel.latitude  = updateVessel.latitude;
                    updateVessel.protoVessel.longitude = updateVessel.longitude;
                    updateVessel.protoVessel.altitude  = updateVessel.altitude;
                    if (!updateVessel.LandedOrSplashed)
                    {
                        //Not landed but under 10km.
                        Vector3d orbitalPos          = updatePostion - updateBody.position;
                        Vector3d surfaceOrbitVelDiff = updateBody.getRFrmVel(updatePostion);
                        Vector3d orbitalVel          = updateVelocity + surfaceOrbitVelDiff;
                        updateVessel.orbitDriver.orbit.UpdateFromStateVectors(orbitalPos.xzy, orbitalVel.xzy, updateBody, Planetarium.GetUniversalTime());
                        updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy;
                        updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel;
                    }
                }
                else
                {
                    double   planetariumDifference = Planetarium.GetUniversalTime() - planetTime;
                    Vector3d positionFudge         = Vector3d.zero;
                    Vector3d velocityFudge         = Vector3d.zero;
                    if (Math.Abs(planetariumDifference) < 3f)
                    {
                        velocityFudge = updateAcceleration * planetariumDifference;
                        //Use the average velocity to determine the new position
                        positionFudge = (updateVelocity + (velocityFudge / 2)) * planetariumDifference;
                    }
                    Vector3d velocityOffset = (updateVelocity + velocityFudge) - updateVessel.srf_velocity;
                    updateVessel.SetPosition(updatePostion + positionFudge, true);
                    updateVessel.ChangeWorldVelocity(velocityOffset);
                }
            }
            else
            {
                Orbit updateOrbit = new Orbit(orbit[0], orbit[1], orbit[2], orbit[3], orbit[4], orbit[5], orbit[6], updateBody);
                updateOrbit.Init();
                updateOrbit.UpdateFromUT(Planetarium.GetUniversalTime());

                if (updateVessel.packed)
                {
                    //The OrbitDriver update call will set the vessel position on the next fixed update
                    VesselUtil.CopyOrbit(updateOrbit, updateVessel.orbitDriver.orbit);
                    updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy;
                    updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel;
                }
                else
                {
                    //Vessel.SetPosition is full of fun and games. Avoid at all costs.
                    //Also, It's quite difficult to figure out the world velocity due to Krakensbane, and the reference frame.
                    Vector3d posDelta = updateOrbit.getPositionAtUT(Planetarium.GetUniversalTime()) - updateVessel.orbitDriver.orbit.getPositionAtUT(Planetarium.GetUniversalTime());
                    Vector3d velDelta = updateOrbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy - updateVessel.orbitDriver.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy;
                    //Vector3d velDelta = updateOrbit.vel.xzy - updateVessel.orbitDriver.orbit.vel.xzy;
                    updateVessel.Translate(posDelta);
                    updateVessel.ChangeWorldVelocity(velDelta);
                }
            }

            //Angular velocity
            //Vector3 angularVelocity = new Vector3(this.angularVelocity[0], this.angularVelocity[1], this.angularVelocity[2]);
            if (updateVessel.parts != null)
            {
                //Vector3 newAng = updateVessel.ReferenceTransform.rotation * angularVelocity;
                foreach (Part vesselPart in updateVessel.parts)
                {
                    if (vesselPart.rb != null && !vesselPart.rb.isKinematic && vesselPart.State == PartStates.ACTIVE)
                    {
                        //The parts can have different rotations - This transforms them into the root part direction which is where the angular velocity is transferred.
                        //vesselPart.rb.angularVelocity = (Quaternion.Inverse(updateVessel.rootPart.rb.rotation) * vesselPart.rb.rotation) * newAng;
                        vesselPart.rb.angularVelocity = Vector3.zero;
                    }
                }
            }

            //Flight state controls (Throttle etc)
            if (!VesselWorker.fetch.isSpectating)
            {
                updateVessel.ctrlState.CopyFrom(flightState);
            }
            else
            {
                FlightInputHandler.state.CopyFrom(flightState);
            }

            //Action group controls
            updateVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, actiongroupControls[0]);
            updateVessel.ActionGroups.SetGroup(KSPActionGroup.Light, actiongroupControls[1]);
            updateVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, actiongroupControls[2]);
            updateVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, actiongroupControls[3]);
            updateVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, actiongroupControls[4]);
        }
Example #44
0
 public extern void UpdateFromOrbitAtUT(Orbit orbit, double UT, CelestialBody toBody);
Example #45
0
 public void IdentifyResourceBand(string resourceName, ResourceBand band, CelestialBody b, bool addScience)
 {
     IdentifyResourceBand(resourceName, band, b.bodyName, addScience);
 }
Example #46
0
 public extern Orbit(double inc, double e, double sma, double lan, double w, double mEp, double t, CelestialBody body);
Example #47
0
 public void DiscoverResourceBand(string resourceName, ResourceBand band, CelestialBody b)
 {
     DiscoverResourceBand(resourceName, band, b.bodyName, true);
 }
Example #48
0
 public void AddIdentifyAtBand(string resourceName, ResourceBand band, CelestialBody b, float amount)
 {
     AddIdentifyAtBand(resourceName, band, b.bodyName, amount);
 }
Example #49
0
 public bool IsDiscovered(string resourceName, string bandName, CelestialBody b)
 {
     return(IsDiscovered(resourceName, bandName, b.bodyName));
 }
Example #50
0
 public void DiscoverResourceBand(string resourceName, ResourceBand band, CelestialBody b, bool addScience)
 {
     DiscoverResourceBand(resourceName, band, b.bodyName, addScience);
 }
Example #51
0
 public void DrawAngle(CelestialBody bodyOrigin, CelestialBody bodyTarget, Double angleTarget)
 {
     DrawAngle(bodyOrigin, bodyTarget);
     AngleTargetValue = angleTarget;
     ShowTargetAngle  = true;
 }
Example #52
0
 public bool IsIdentified(string resourceName, string bandName, CelestialBody b)
 {
     return(IsIdentified(resourceName, bandName, b.bodyName));
 }
Example #53
0
 public IBodyResources Load(CelestialBody body, ConfigNode node)
 {
     return(new BodyDeposits(config.ForBody(body), node));
 }
Example #54
0
        private IEnumerable <bool> AddPatch(VesselState startingState, bool isActiveVessel)
        {
            if (isActiveVessel)
            {
                if (null == attachedVessel.patchedConicSolver)
                {
                    UnityEngine.Debug.LogWarning("Trajectories: AddPatch() attempted when patchedConicsSolver is null; Skipping.");
                    yield break;
                }
            }

            CelestialBody body = startingState.ReferenceBody;

            var patch = new Patch
            {
                StartingState = startingState,
                IsAtmospheric = false,
                SpaceOrbit    = startingState.StockPatch ?? CreateOrbitFromState(startingState)
            };

            patch.EndTime = patch.StartingState.Time + patch.SpaceOrbit.period;

            // the flight plan does not always contain the first patches (before the first maneuver node),
            // so we populate it with the current orbit and associated encounters etc.
            var flightPlan = new List <Orbit>();

            for (var orbit = attachedVessel.orbit; orbit != null && orbit.activePatch; orbit = orbit.nextPatch)
            {
                flightPlan.Add(orbit);
            }


            Orbit nextPatch = null;

            if (startingState.StockPatch == null)
            {
                nextPatch = patch.SpaceOrbit.nextPatch;
            }
            else
            {
                int planIdx = flightPlan.IndexOf(startingState.StockPatch);
                if (planIdx >= 0 && planIdx < flightPlan.Count - 1)
                {
                    nextPatch = flightPlan[planIdx + 1];
                }
            }

            if (nextPatch != null)
            {
                patch.EndTime = nextPatch.StartUT;
            }

            double maxAtmosphereAltitude = RealMaxAtmosphereAltitude(body);

            if (!body.atmosphere)
            {
                maxAtmosphereAltitude = body.pqsController.mapMaxHeight;
            }

            double minAltitude = patch.SpaceOrbit.PeA;

            if (patch.SpaceOrbit.timeToPe < 0 || patch.EndTime < startingState.Time + patch.SpaceOrbit.timeToPe)
            {
                minAltitude = Math.Min(
                    patch.SpaceOrbit.getRelativePositionAtUT(patch.EndTime).magnitude,
                    patch.SpaceOrbit.getRelativePositionAtUT(patch.StartingState.Time + 1.0).magnitude
                    ) - body.Radius;
            }
            if (minAltitude < maxAtmosphereAltitude)
            {
                double entryTime;
                if (startingState.Position.magnitude <= body.Radius + maxAtmosphereAltitude)
                {
                    // whole orbit is inside the atmosphere
                    entryTime = startingState.Time;
                }
                else
                {
                    entryTime = FindOrbitBodyIntersection(
                        patch.SpaceOrbit,
                        startingState.Time, startingState.Time + patch.SpaceOrbit.timeToPe,
                        body.Radius + maxAtmosphereAltitude);
                }

                if (entryTime > startingState.Time + 0.1 || !body.atmosphere)
                {
                    if (body.atmosphere)
                    {
                        // add the space patch before atmospheric entry

                        patch.EndTime = entryTime;
                        patchesBackBuffer_.Add(patch);
                        AddPatch_outState = new VesselState
                        {
                            Position      = SwapYZ(patch.SpaceOrbit.getRelativePositionAtUT(entryTime)),
                            ReferenceBody = body,
                            Time          = entryTime,
                            Velocity      = SwapYZ(patch.SpaceOrbit.getOrbitalVelocityAtUT(entryTime))
                        };
                        yield break;
                    }
                    else
                    {
                        // the body has no atmosphere, so what we actually computed is the entry
                        // inside the "ground sphere" (defined by the maximal ground altitude)
                        // now we iterate until the inner ground sphere (minimal altitude), and
                        // check if we hit the ground along the way
                        double groundRangeExit = FindOrbitBodyIntersection(
                            patch.SpaceOrbit,
                            startingState.Time, startingState.Time + patch.SpaceOrbit.timeToPe,
                            body.Radius - maxAtmosphereAltitude);

                        if (groundRangeExit <= entryTime)
                        {
                            groundRangeExit = startingState.Time + patch.SpaceOrbit.timeToPe;
                        }

                        double iterationSize = (groundRangeExit - entryTime) / 100.0;
                        double t;
                        bool   groundImpact = false;
                        for (t = entryTime; t < groundRangeExit; t += iterationSize)
                        {
                            Vector3d pos            = patch.SpaceOrbit.getRelativePositionAtUT(t);
                            double   groundAltitude = GetGroundAltitude(body, CalculateRotatedPosition(body, SwapYZ(pos), t))
                                                      + body.Radius;
                            if (pos.magnitude < groundAltitude)
                            {
                                t           -= iterationSize;
                                groundImpact = true;
                                break;
                            }
                        }

                        if (groundImpact)
                        {
                            patch.EndTime           = t;
                            patch.RawImpactPosition = SwapYZ(patch.SpaceOrbit.getRelativePositionAtUT(t));
                            patch.ImpactPosition    = CalculateRotatedPosition(body, patch.RawImpactPosition.Value, t);
                            patch.ImpactVelocity    = SwapYZ(patch.SpaceOrbit.getOrbitalVelocityAtUT(t));
                            patchesBackBuffer_.Add(patch);
                            AddPatch_outState = null;
                            yield break;
                        }
                        else
                        {
                            // no impact, just add the space orbit
                            patchesBackBuffer_.Add(patch);
                            if (nextPatch != null)
                            {
                                AddPatch_outState = new VesselState
                                {
                                    Position      = SwapYZ(patch.SpaceOrbit.getRelativePositionAtUT(patch.EndTime)),
                                    Velocity      = SwapYZ(patch.SpaceOrbit.getOrbitalVelocityAtUT(patch.EndTime)),
                                    ReferenceBody = nextPatch == null ? body : nextPatch.referenceBody,
                                    Time          = patch.EndTime,
                                    StockPatch    = nextPatch
                                };
                                yield break;
                            }
                            else
                            {
                                AddPatch_outState = null;
                                yield break;
                            }
                        }
                    }
                }
                else
                {
                    if (patch.StartingState.ReferenceBody != attachedVessel.mainBody)
                    {
                        // currently, we can't handle predictions for another body, so we stop
                        AddPatch_outState = null;
                        yield break;
                    }

                    // simulate atmospheric flight (drag and lift), until impact or atmosphere exit
                    // (typically for an aerobraking maneuver) assuming a constant angle of attack
                    patch.IsAtmospheric            = true;
                    patch.StartingState.StockPatch = null;

                    // lower dt would be more accurate, but a tradeoff has to be found between performances and accuracy
                    double dt = Settings.IntegrationStepSize;

                    // some shallow entries can result in very long flight. For performances reasons,
                    // we limit the prediction duration
                    int maxIterations = (int)(60.0 * 60.0 / dt);

                    int chunkSize = 128;

                    // time between two consecutive stored positions (more intermediate positions are computed for better accuracy),
                    // also used for ground collision checks
                    double trajectoryInterval = 10.0;

                    var buffer = new List <Point[]>
                    {
                        new Point[chunkSize]
                    };
                    int nextPosIdx = 0;

                    SimulationState state;
                    state.position = SwapYZ(patch.SpaceOrbit.getRelativePositionAtUT(entryTime));
                    state.velocity = SwapYZ(patch.SpaceOrbit.getOrbitalVelocityAtUT(entryTime));

                    // Initialize a patch with zero acceleration
                    Vector3d currentAccel = new Vector3d(0.0, 0.0, 0.0);


                    double   currentTime               = entryTime;
                    double   lastPositionStoredUT      = 0;
                    Vector3d lastPositionStored        = new Vector3d();
                    bool     hitGround                 = false;
                    int      iteration                 = 0;
                    int      incrementIterations       = 0;
                    int      minIterationsPerIncrement = maxIterations / Settings.MaxFramesPerPatch;

                    #region Acceleration Functor

                    // function that calculates the acceleration under current parmeters
                    Func <Vector3d, Vector3d, Vector3d> accelerationFunc = (position, velocity) =>
                    {
                        //Profiler.Start("accelerationFunc inside");

                        // gravity acceleration
                        double   R_      = position.magnitude;
                        Vector3d accel_g = position * (-body.gravParameter / (R_ * R_ * R_));

                        // aero force
                        Vector3d vel_air = velocity - body.getRFrmVel(body.position + position);

                        double aoa = 0;

                        //Profiler.Start("GetForces");
                        Vector3d force_aero = aerodynamicModel_.GetForces(body, position, vel_air, aoa);
                        //Profiler.Stop("GetForces");

                        Vector3d accel = accel_g + force_aero / aerodynamicModel_.mass;

                        //Profiler.Stop("accelerationFunc inside");
                        return(accel);
                    };
                    #endregion


                    #region Integration Loop

                    while (true)
                    {
                        ++iteration;
                        ++incrementIterations;

                        if (incrementIterations > minIterationsPerIncrement && incrementTime_.ElapsedMilliseconds > MaxIncrementTime)
                        {
                            yield return(false);

                            incrementIterations = 0;
                        }


                        double R               = state.position.magnitude;
                        double altitude        = R - body.Radius;
                        double atmosphereCoeff = altitude / maxAtmosphereAltitude;
                        if (hitGround ||
                            atmosphereCoeff <= 0.0 || atmosphereCoeff >= 1.0 ||
                            iteration == maxIterations || currentTime > patch.EndTime)
                        {
                            //Util.PostSingleScreenMessage("atmo force", "Atmospheric accumulated force: " + accumulatedForces.ToString("0.00"));

                            if (hitGround || atmosphereCoeff <= 0.0)
                            {
                                patch.RawImpactPosition = state.position;
                                patch.ImpactPosition    = CalculateRotatedPosition(body, patch.RawImpactPosition.Value, currentTime);
                                patch.ImpactVelocity    = state.velocity;
                            }

                            patch.EndTime = Math.Min(currentTime, patch.EndTime);

                            int totalCount = (buffer.Count - 1) * chunkSize + nextPosIdx;
                            patch.AtmosphericTrajectory = new Point[totalCount];
                            int outIdx = 0;
                            foreach (var chunk in buffer)
                            {
                                foreach (var p in chunk)
                                {
                                    if (outIdx == totalCount)
                                    {
                                        break;
                                    }
                                    patch.AtmosphericTrajectory[outIdx++] = p;
                                }
                            }

                            if (iteration == maxIterations)
                            {
                                ScreenMessages.PostScreenMessage("WARNING: trajectory prediction stopped, too many iterations");
                                patchesBackBuffer_.Add(patch);
                                AddPatch_outState = null;
                                yield break;
                            }
                            else if (atmosphereCoeff <= 0.0 || hitGround)
                            {
                                patchesBackBuffer_.Add(patch);
                                AddPatch_outState = null;
                                yield break;
                            }
                            else
                            {
                                patchesBackBuffer_.Add(patch);
                                AddPatch_outState = new VesselState
                                {
                                    Position      = state.position,
                                    Velocity      = state.velocity,
                                    ReferenceBody = body,
                                    Time          = patch.EndTime
                                };
                                yield break;
                            }
                        }

                        Vector3d        lastAccel = currentAccel;
                        SimulationState lastState = state;

                        //Profiler.Start("IntegrationStep");

                        // Verlet integration (more precise than using the velocity)
                        // state = VerletStep(state, accelerationFunc, dt);
                        state = RK4Step(state, accelerationFunc, dt, out currentAccel);

                        currentTime += dt;

                        // KSP presumably uses Euler integration for position updates. Since RK4 is actually more precise than that,
                        // we try to reintroduce an approximation of the error.

                        // The local truncation error for euler integration is:
                        // LTE = 1/2 * h^2 * y''(t)
                        // https://en.wikipedia.org/wiki/Euler_method#Local_truncation_error
                        //
                        // For us,
                        // h is the time step of the outer simulation (KSP), which is the physics time step
                        // y''(t) is the difference of the velocity/acceleration divided by the physics time step
                        state.position += 0.5 * TimeWarp.fixedDeltaTime * currentAccel * dt;
                        state.velocity += 0.5 * TimeWarp.fixedDeltaTime * (currentAccel - lastAccel);

                        //Profiler.Stop("IntegrationStep");

                        // calculate gravity and aerodynamic force
                        Vector3d gravityAccel     = lastState.position * (-body.gravParameter / (R * R * R));
                        Vector3d aerodynamicForce = (currentAccel - gravityAccel) / aerodynamicModel_.mass;

                        // acceleration in the vessel reference frame is acceleration - gravityAccel
                        maxAccelBackBuffer_ = Math.Max(
                            (float)(aerodynamicForce.magnitude / aerodynamicModel_.mass),
                            maxAccelBackBuffer_);

                        #region Impact Calculation

                        //Profiler.Start("AddPatch#impact");

                        double interval = altitude < 10000.0 ? trajectoryInterval * 0.1 : trajectoryInterval;
                        if (currentTime >= lastPositionStoredUT + interval)
                        {
                            double groundAltitude = GetGroundAltitude(body, CalculateRotatedPosition(body, state.position, currentTime));
                            if (lastPositionStoredUT > 0)
                            {
                                // check terrain collision, to detect impact on mountains etc.
                                Vector3 rayOrigin         = lastPositionStored;
                                Vector3 rayEnd            = state.position;
                                double  absGroundAltitude = groundAltitude + body.Radius;
                                if (absGroundAltitude > rayEnd.magnitude)
                                {
                                    hitGround = true;
                                    float coeff = Math.Max(0.01f, (float)((absGroundAltitude - rayOrigin.magnitude)
                                                                          / (rayEnd.magnitude - rayOrigin.magnitude)));
                                    state.position = rayEnd * coeff + rayOrigin * (1.0f - coeff);
                                    currentTime    = currentTime * coeff + lastPositionStoredUT * (1.0f - coeff);
                                }
                            }

                            lastPositionStoredUT = currentTime;
                            if (nextPosIdx == chunkSize)
                            {
                                buffer.Add(new Point[chunkSize]);
                                nextPosIdx = 0;
                            }
                            Vector3d nextPos = state.position;
                            if (Settings.BodyFixedMode)
                            {
                                nextPos = CalculateRotatedPosition(body, nextPos, currentTime);
                            }
                            buffer.Last()[nextPosIdx].aerodynamicForce = aerodynamicForce;
                            buffer.Last()[nextPosIdx].orbitalVelocity  = state.velocity;
                            buffer.Last()[nextPosIdx].groundAltitude   = (float)groundAltitude;
                            buffer.Last()[nextPosIdx].time             = currentTime;
                            buffer.Last()[nextPosIdx++].pos            = nextPos;
                            lastPositionStored = state.position;
                        }

                        //Profiler.Stop("AddPatch#impact");

                        #endregion
                    }

                    #endregion
                }
            }
            else
            {
                // no atmospheric entry, just add the space orbit
                patchesBackBuffer_.Add(patch);
                if (nextPatch != null)
                {
                    AddPatch_outState = new VesselState
                    {
                        Position      = SwapYZ(patch.SpaceOrbit.getRelativePositionAtUT(patch.EndTime)),
                        Velocity      = SwapYZ(patch.SpaceOrbit.getOrbitalVelocityAtUT(patch.EndTime)),
                        ReferenceBody = nextPatch == null ? body : nextPatch.referenceBody,
                        Time          = patch.EndTime,
                        StockPatch    = nextPatch
                    };
                    yield break;
                }
                else
                {
                    AddPatch_outState = null;
                    yield break;
                }
            }
        }
Example #55
0
 public static float TerrainHeight(double lat, double lon, CelestialBody body)
 {
     return(0);
 }
Example #56
0
 public GeneratorConfiguration ForBody(CelestialBody body)
 {
     return(bodies.ContainsKey(body.name) ? bodies[body.name] : this);
 }
Example #57
0
        private void InitRunwaysList()
        {
            runways = new List <Runway>();

            // Import landing sites form a user createded .cfg
            foreach (var mjConf in GameDatabase.Instance.GetConfigs("MechJeb2Landing"))
            {
                foreach (ConfigNode site in mjConf.config.GetNode("Runways").GetNodes("Runway"))
                {
                    string     runwayName = site.GetValue("name");
                    ConfigNode start      = site.GetNode("start");
                    ConfigNode end        = site.GetNode("end");

                    if (runwayName == null || start == null || end == null)
                    {
                        continue;
                    }

                    string lat = start.GetValue("latitude");
                    string lon = start.GetValue("longitude");
                    string alt = start.GetValue("altitude");

                    if (lat == null || lon == null || alt == null)
                    {
                        continue;
                    }

                    double startLatitude, startLongitude, startAltitude;
                    double.TryParse(lat, out startLatitude);
                    double.TryParse(lon, out startLongitude);
                    double.TryParse(alt, out startAltitude);

                    lat = end.GetValue("latitude");
                    lon = end.GetValue("longitude");
                    alt = end.GetValue("altitude");

                    if (lat == null || lon == null || alt == null)
                    {
                        continue;
                    }

                    double endLatitude, endLongitude, endAltitude;
                    double.TryParse(lat, out endLatitude);
                    double.TryParse(lon, out endLongitude);
                    double.TryParse(alt, out endAltitude);

                    string        bodyName = site.GetValue("body");
                    CelestialBody body     = bodyName != null?FlightGlobals.Bodies.Find(b => b.bodyName == bodyName) : Planetarium.fetch.Home;

                    if (body != null && !runways.Any(p => p.name == runwayName))
                    {
                        runways.Add(new Runway()
                        {
                            name  = runwayName,
                            body  = body,
                            start = new Runway.Endpoint {
                                latitude = startLatitude, longitude = startLongitude, altitude = startAltitude
                            },
                            end = new Runway.Endpoint {
                                latitude = endLatitude, longitude = endLongitude, altitude = endAltitude
                            }
                        });
                    }
                }
            }

            // Create a default config file in MJ dir for those ?
            if (!runways.Any(p => p.name == "KSC runway"))
            {
                runways.Add(new Runway //The runway at KSC
                {
                    name  = "KSC runway",
                    body  = Planetarium.fetch.Home,
                    start = new Runway.Endpoint {
                        latitude = -0.050185, longitude = -74.490867, altitude = 69.01
                    },
                    end = new Runway.Endpoint {
                        latitude = -0.0485981, longitude = -74.726413, altitude = 69.01
                    }
                });
            }

            if (!runways.Any(p => p.name == "Island runway"))
            {
                runways.Add(new Runway //The runway on the island off the KSC coast.
                {
                    name  = "Island runway",
                    body  = Planetarium.fetch.Home,
                    start = new Runway.Endpoint {
                        latitude = -1.517306, longitude = -71.965488, altitude = 133.17
                    },
                    end = new Runway.Endpoint {
                        latitude = -1.515980, longitude = -71.852408, altitude = 133.17
                    }
                });
            }
        }
Example #58
0
        public static string TestRequirements(string experiment_id, string requirements, Vessel v)
        {
            CelestialBody body = v.mainBody;
            Vessel_info   vi   = Cache.VesselInfo(v);

            List <string> list = Lib.Tokenize(requirements, ',');

            foreach (string s in list)
            {
                var parts = Lib.Tokenize(s, ':');

                var    condition = parts[0];
                string value     = string.Empty;
                if (parts.Count > 1)
                {
                    value = parts[1];
                }

                bool good = true;
                switch (condition)
                {
                case "OrbitMinInclination": good = v.orbit.inclination >= double.Parse(value); break;

                case "OrbitMaxInclination": good = v.orbit.inclination <= double.Parse(value); break;

                case "OrbitMinEccentricity": good = v.orbit.eccentricity >= double.Parse(value); break;

                case "OrbitMaxEccentricity": good = v.orbit.eccentricity <= double.Parse(value); break;

                case "OrbitMinArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis >= double.Parse(value); break;

                case "OrbitMaxArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis <= double.Parse(value); break;

                case "TemperatureMin": good = vi.temperature >= double.Parse(value); break;

                case "TemperatureMax": good = vi.temperature <= double.Parse(value); break;

                case "AltitudeMin": good = v.altitude >= double.Parse(value); break;

                case "AltitudeMax": good = v.altitude <= double.Parse(value); break;

                case "RadiationMin": good = vi.radiation >= double.Parse(value); break;

                case "RadiationMax": good = vi.radiation <= double.Parse(value); break;

                case "Microgravity": good = vi.zerog; break;

                case "Body": good = TestBody(v.mainBody.name, value); break;

                case "Shadow": good = vi.sunlight < double.Epsilon; break;

                case "Sunlight": good = vi.sunlight > 0.5; break;

                case "CrewMin": good = vi.crew_count >= int.Parse(value); break;

                case "CrewMax": good = vi.crew_count <= int.Parse(value); break;

                case "CrewCapacityMin": good = vi.crew_capacity >= int.Parse(value); break;

                case "CrewCapacityMax": good = vi.crew_capacity <= int.Parse(value); break;

                case "VolumePerCrewMin": good = vi.volume_per_crew >= double.Parse(value); break;

                case "VolumePerCrewMax": good = vi.volume_per_crew <= double.Parse(value); break;

                case "Greenhouse": good = vi.greenhouses.Count > 0; break;

                case "Surface": good = Lib.Landed(v); break;

                case "Atmosphere": good = body.atmosphere && v.altitude < body.atmosphereDepth; break;

                case "AtmosphereBody": good = body.atmosphere; break;

                case "AtmosphereAltMin": good = body.atmosphere && (v.altitude / body.atmosphereDepth) >= double.Parse(value); break;

                case "AtmosphereAltMax": good = body.atmosphere && (v.altitude / body.atmosphereDepth) <= double.Parse(value); break;

                case "SunAngleMin": good = Lib.SunBodyAngle(v) >= double.Parse(value); break;

                case "SunAngleMax": good = Lib.SunBodyAngle(v) <= double.Parse(value); break;

                case "Vacuum": good = !body.atmosphere || v.altitude > body.atmosphereDepth; break;

                case "Ocean": good = body.ocean && v.altitude < 0.0; break;

                case "PlanetarySpace": good = body.flightGlobalsIndex != 0 && !Lib.Landed(v) && v.altitude > body.atmosphereDepth; break;

                case "AbsoluteZero": good = vi.temperature < 30.0; break;

                case "InnerBelt": good = vi.inner_belt; break;

                case "OuterBelt": good = vi.outer_belt; break;

                case "MagneticBelt": good = vi.inner_belt || vi.outer_belt; break;

                case "Magnetosphere": good = vi.magnetosphere; break;

                case "Thermosphere": good = vi.thermosphere; break;

                case "Exosphere": good = vi.exosphere; break;

                case "InterPlanetary": good = body.flightGlobalsIndex == 0 && !vi.interstellar; break;

                case "InterStellar": good = body.flightGlobalsIndex == 0 && vi.interstellar; break;

                case "SurfaceSpeedMin": good = v.srfSpeed >= double.Parse(value); break;

                case "SurfaceSpeedMax": good = v.srfSpeed <= double.Parse(value); break;

                case "VerticalSpeedMin": good = v.verticalSpeed >= double.Parse(value); break;

                case "VerticalSpeedMax": good = v.verticalSpeed <= double.Parse(value); break;

                case "SpeedMin": good = v.speed >= double.Parse(value); break;

                case "SpeedMax": good = v.speed <= double.Parse(value); break;

                case "DynamicPressureMin": good = v.dynamicPressurekPa >= double.Parse(value); break;

                case "DynamicPressureMax": good = v.dynamicPressurekPa <= double.Parse(value); break;

                case "StaticPressureMin": good = v.staticPressurekPa >= double.Parse(value); break;

                case "StaticPressureMax": good = v.staticPressurekPa <= double.Parse(value); break;

                case "AtmDensityMin": good = v.atmDensity >= double.Parse(value); break;

                case "AtmDensityMax": good = v.atmDensity <= double.Parse(value); break;

                case "AltAboveGroundMin": good = v.heightFromTerrain >= double.Parse(value); break;

                case "AltAboveGroundMax": good = v.heightFromTerrain <= double.Parse(value); break;

                case "Part": good = Lib.HasPart(v, value); break;

                case "Module": good = Lib.FindModules(v.protoVessel, value).Count > 0; break;

                case "AstronautComplexLevelMin":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "AstronautComplexLevelMax":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "TrackingStationLevelMin":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "TrackingStationLevelMax":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "MissionControlLevelMin":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "MissionControlLevelMax":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "AdministrationLevelMin":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "AdministrationLevelMax":
                    good = !ScenarioUpgradeableFacilities.Instance.enabled || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "MaxAsteroidDistance": good = AsteroidDistance(v) <= double.Parse(value); break;
                }

                if (!good)
                {
                    return(s);
                }
            }

            var subject_id = Science.Generate_subject_id(experiment_id, v);
            var exp        = Science.Experiment(subject_id);
            var sit        = GetExperimentSituation(v);

            if (!sit.IsAvailable(exp))
            {
                return("Invalid situation");
            }


            // At this point we know the situation is valid and the experiment can be done
            // create it in R&D
            Science.Generate_subject(experiment_id, v);

            return(string.Empty);
        }
Example #59
0
        // return the total environent radiation at position specified
        public static double Compute(Vessel v, Vector3d position, double gamma_transparency, double sunlight, out bool blackout,
                                     out bool magnetosphere, out bool inner_belt, out bool outer_belt, out bool interstellar)
        {
            // prepare out parameters
            blackout      = false;
            magnetosphere = false;
            inner_belt    = false;
            outer_belt    = false;
            interstellar  = false;

            // no-op when Radiation is disabled
            if (!Features.Radiation)
            {
                return(0.0);
            }

            // store stuff
            Space   gsm;
            Vector3 p;
            float   D;

            // transform to local space once
            position = ScaledSpace.LocalToScaledSpace(position);

            // accumulate radiation
            double        radiation = 0.0;
            CelestialBody body      = v.mainBody;

            while (body != null)
            {
                RadiationBody  rb = Info(body);
                RadiationModel mf = rb.model;
                if (mf.Has_field())
                {
                    // generate radii-normalized GSM space
                    gsm = Gsm_space(rb, true);

                    // move the point in GSM space
                    p = gsm.Transform_in(position);

                    // accumulate radiation and determine pause/belt flags
                    if (mf.has_inner)
                    {
                        D           = mf.Inner_func(p);
                        radiation  += Lib.Clamp(D / -0.0666f, 0.0f, 1.0f) * rb.radiation_inner;
                        inner_belt |= D < 0.0f;
                    }
                    if (mf.has_outer)
                    {
                        D           = mf.Outer_func(p);
                        radiation  += Lib.Clamp(D / -0.0333f, 0.0f, 1.0f) * rb.radiation_outer;
                        outer_belt |= D < 0.0f;
                    }
                    if (mf.has_pause)
                    {
                        gsm = Gsm_space(rb, false);
                        p   = gsm.Transform_in(position);

                        D              = mf.Pause_func(p);
                        radiation     += Lib.Clamp(D / -0.1332f, 0.0f, 1.0f) * rb.radiation_pause;
                        magnetosphere |= D < 0.0f && rb.body.flightGlobalsIndex != 0;                        //< ignore heliopause
                        interstellar  |= D > 0.0f && rb.body.flightGlobalsIndex == 0;                        //< outside heliopause
                    }
                }

                // avoid loops in the chain
                body = (body.referenceBody != null && body.referenceBody.referenceBody == body) ? null : body.referenceBody;
            }

            // add extern radiation
            radiation += PreferencesStorm.Instance.ExternRadiation;

            // add emitter radiation
            radiation += Emitter.Total(v);

            // if there is a storm in progress
            if (Storm.InProgress(v))
            {
                // inside a magnetopause (except heliosphere), blackout the signal
                // outside, add storm radiations modulated by sun visibility
                if (magnetosphere)
                {
                    blackout = true;
                }
                else
                {
                    radiation += PreferencesStorm.Instance.StormRadiation * sunlight;
                }
            }

            // clamp radiation to positive range
            // note: we avoid radiation going to zero by using a small positive value
            radiation = Math.Max(radiation, Nominal);

            // return radiation, scaled by gamma transparency if inside atmosphere
            return(radiation * gamma_transparency);
        }
Example #60
0
        /// <summary>
        /// Loads the contract type details from the given config node.
        /// </summary>
        /// <param name="configNode">The config node to load from.</param>
        /// <returns>Whether the load was successful.</returns>
        public bool Load(ConfigNode configNode)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;

            try
            {
                // Logging on
                LoggingUtil.CaptureLog = true;
                ConfigNodeUtil.SetCurrentDataNode(null);
                LoggingUtil.LogInfo(this, "Loading CONTRACT_TYPE: '" + name + "'");

                // Clear the config node cache
                ConfigNodeUtil.ClearCache(true);

                // Load values that are immediately required
                bool valid = true;
                valid &= ConfigNodeUtil.ParseValue <ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null);

                // Set up the data node
                dataNode = new DataNode(configNode.GetValue("name"), group != null ? group.dataNode : null, this);
                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "name", x => name = x, this);

                // Try to turn on trace mode
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "trace", x => trace = x, this, false);
                if (trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                    LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name);
                }

                // Load contract text details
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "title", x => title = x, this);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "tag", x => tag = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "description", x => description = x, this, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "topic", x => topic = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "subject", x => subject = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "motivation", x => motivation = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "notes", x => notes = x, this, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "synopsis", x => synopsis = x, this);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "completedMessage", x => completedMessage = x, this);

                // Load optional attributes
                valid &= ConfigNodeUtil.ParseValue <Agent>(configNode, "agent", x => agent = x, this, group != null ? group.agent : null);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "minExpiry", x => minExpiry = x, this, 5.0f, x => Validation.GE(x, 0.0f));
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "maxExpiry", x => maxExpiry = x, this, 100.0f, x => Validation.GE(x, minExpiry));
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "deadline", x => deadline = x, this, 0.0f, x => Validation.GE(x, 0.0f));
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "cancellable", x => cancellable = x, this, true);
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "declinable", x => declinable = x, this, true);
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "autoAccept", x => autoAccept = x, this, false);
                valid &= ConfigNodeUtil.ParseValue <List <Contract.ContractPrestige> >(configNode, "prestige", x => prestige = x, this, new List <Contract.ContractPrestige>());
                valid &= ConfigNodeUtil.ParseValue <CelestialBody>(configNode, "targetBody", x => targetBody = x, this, (CelestialBody)null);

                valid &= ConfigNodeUtil.ParseValue <int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0));
                valid &= ConfigNodeUtil.ParseValue <int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, (maxCompletions == 0 ? 4 : 0), x => Validation.GE(x, 0));

                // Load rewards
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardFunds", x => rewardFunds = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardReputation", x => rewardReputation = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardScience", x => rewardScience = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "failureFunds", x => failureFunds = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "failureReputation", x => failureReputation = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "advanceFunds", x => advanceFunds = x, this, 0.0f);

                // Load other values
                if (configNode.HasValue("weight"))
                {
                    valid &= ConfigNodeUtil.ParseValue <double>(configNode, "weight", x => {}, this);
                    LoggingUtil.LogWarning(this, ErrorPrefix() + ": The weight attribute is deprecated as of Contract Configurator 1.15.0.  Contracts are no longer generated using a weighted system.");
                }

                // Merge in data from the parent contract group
                for (ContractGroup currentGroup = group; currentGroup != null; currentGroup = currentGroup.parent)
                {
                    // Merge dataValues - this is a flag saying what values need to be unique at the contract level
                    foreach (KeyValuePair <string, DataValueInfo> pair in currentGroup.dataValues)
                    {
                        dataValues[currentGroup.name + ":" + pair.Key] = pair.Value;
                    }

                    // Merge uniquenessChecks
                    foreach (KeyValuePair <string, DataNode.UniquenessCheck> pair in currentGroup.uniquenessChecks)
                    {
                        uniquenessChecks[currentGroup.name + ":" + pair.Key] = pair.Value;
                    }
                }

                // Load DATA nodes
                valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks);

                log = LoggingUtil.capturedLog;
                LoggingUtil.CaptureLog = false;

                // Load parameters
                foreach (ConfigNode contractParameter in ConfigNodeUtil.GetChildNodes(configNode, "PARAMETER"))
                {
                    ParameterFactory paramFactory = null;
                    valid &= ParameterFactory.GenerateParameterFactory(contractParameter, this, out paramFactory);
                    if (paramFactory != null)
                    {
                        paramFactories.Add(paramFactory);
                        if (paramFactory.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Load behaviours
                foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "BEHAVIOUR"))
                {
                    BehaviourFactory behaviourFactory = null;
                    valid &= BehaviourFactory.GenerateBehaviourFactory(requirementNode, this, out behaviourFactory);
                    if (behaviourFactory != null)
                    {
                        behaviourFactories.Add(behaviourFactory);
                        if (behaviourFactory.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Load requirements
                foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT"))
                {
                    ContractRequirement requirement = null;
                    valid &= ContractRequirement.GenerateRequirement(requirementNode, this, out requirement);
                    if (requirement != null)
                    {
                        requirements.Add(requirement);
                        if (requirement.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Logging on
                LoggingUtil.CaptureLog = true;

                // Check we have at least one valid parameter
                if (paramFactories.Count() == 0)
                {
                    LoggingUtil.LogError(this, ErrorPrefix() + ": Need at least one parameter for a contract!");
                    valid = false;
                }

                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                //
                // Process the DATA_EXPAND nodes - this could cause a restart to the load process
                //
                ConfigNode dataExpandNode = configNode.GetNodes("DATA_EXPAND").FirstOrDefault();
                if (dataExpandNode != null)
                {
                    Type type = null;
                    valid &= ConfigNodeUtil.ParseValue <Type>(dataExpandNode, "type", x => type = x, this);

                    if (type != null)
                    {
                        foreach (ConfigNode.Value pair in dataExpandNode.values)
                        {
                            string key = pair.name;
                            if (key != "type")
                            {
                                object value = null;

                                // Create the setter function
                                Type actionType = typeof(Action <>).MakeGenericType(type);
                                Delegate.CreateDelegate(actionType, value, typeof(DataNode).GetMethod("NullAction"));

                                // Set the ParseDataExpandString method generic value
                                MethodInfo method = methodParseExpand.MakeGenericMethod(new Type[] { type });

                                // Invoke the ParseDataExpandString method
                                List <string> values = (List <string>)method.Invoke(this, new object[] { dataExpandNode, key });

                                // Stop at this point if we're invalid
                                if (values == null || !valid)
                                {
                                    if (values == null)
                                    {
                                        LoggingUtil.LogWarning(this, ErrorPrefix() + ": Received an empty list of values when trying to do a DATA_EXPAND");
                                    }
                                    valid = false;
                                    break;
                                }

                                // Expand
                                configNode.RemoveNode(dataExpandNode);
                                foreach (string val in values)
                                {
                                    // Set up for expansion
                                    ConfigNode copy    = configNode.CreateCopy();
                                    string     newName = name + "." + val;
                                    copy.SetValue("name", newName);

                                    // Set up the data node in the copy
                                    ConfigNode dataNode = new ConfigNode("DATA");
                                    copy.AddNode(dataNode);
                                    dataNode.AddValue("type", dataExpandNode.GetValue("type"));
                                    dataNode.AddValue(key, val);

                                    ContractType contractTypeCopy = new ContractType(newName);
                                    contractTypeCopy.Load(copy);
                                }

                                // Remove the original
                                contractTypes.Remove(name);

                                // Don't do any more loading for this one
                                LoggingUtil.LogInfo(this, "Successfully expanded CONTRACT_TYPE '" + name + "'");
                                return(valid);
                            }
                        }
                    }
                }

                //
                // Do the deferred loads
                //
                valid &= ConfigNodeUtil.ExecuteDeferredLoads();

                //
                // Do generic fields that need to happen after deferred loads
                //
                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                // Generic title
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "genericTitle", x => genericTitle = x, this, title);
                if (!configNode.HasValue("genericTitle") && !dataNode.IsDeterministic("title"))
                {
                    LoggingUtil.Log(minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING, this,
                                    ErrorPrefix() + ": The field 'genericTitle' is required when the title is not determistic (ie. when expressions are used).");

                    // Error on newer versions of contract packs
                    if (minVersion >= ContractConfigurator.ENHANCED_UI_VERSION)
                    {
                        valid = false;
                    }
                }
                else if (!dataNode.IsDeterministic("genericTitle"))
                {
                    valid = false;
                    LoggingUtil.LogError(this, ErrorPrefix() + ": The field 'genericTitle' must be deterministic.");
                }

                // Generic description
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "genericDescription", x => genericDescription = x, this, description);
                if (!configNode.HasValue("genericDescription") && !dataNode.IsDeterministic("description"))
                {
                    LoggingUtil.Log(minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING, this,
                                    ErrorPrefix() + ": The field 'genericDescription' is required when the description is not determistic (ie. when expressions are used).");

                    // Error on newer versions of contract packs
                    if (minVersion >= ContractConfigurator.ENHANCED_UI_VERSION)
                    {
                        valid = false;
                    }
                }
                else if (!dataNode.IsDeterministic("genericDescription"))
                {
                    valid = false;
                    LoggingUtil.LogError(this, ErrorPrefix() + ": The field 'genericDescription' must be deterministic.");
                }

                // Sorting key
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "sortKey", x => sortKey = x, this, genericTitle);

                // Check for unexpected values - always do this last
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this);

                if (valid)
                {
                    LoggingUtil.LogInfo(this, "Successfully loaded CONTRACT_TYPE '" + name + "'");
                }
                else
                {
                    LoggingUtil.LogWarning(this, "Errors encountered while trying to load CONTRACT_TYPE '" + name + "'");
                }
                config  = configNode.ToString();
                hash    = config.GetHashCode();
                enabled = valid;
                log    += LoggingUtil.capturedLog;

                if (LoggingUtil.logLevel >= LoggingUtil.LogLevel.DEBUG)
                {
                    // Get the contract configurator log file
                    string[] dirComponents  = new string[] { KSPUtil.ApplicationRootPath, "GameData", "ContractConfigurator", "log", (group == null ? "!NO_GROUP" : group.Root.name) };
                    string[] pathComponents = dirComponents.Union(new string[] { name + ".log" }).ToArray();
                    string   dir            = string.Join(Path.DirectorySeparatorChar.ToString(), dirComponents);
                    string   path           = string.Join(Path.DirectorySeparatorChar.ToString(), pathComponents);

                    // Delete the file if it exists
                    if (File.Exists(path))
                    {
                        try
                        {
                            File.Delete(path);
                        }
                        catch (Exception e)
                        {
                            LoggingUtil.LogException(new Exception("Exception while attempting to delete the file: " + path, e));
                        }
                    }

                    // Create the directory if it doesn't exist
                    Directory.CreateDirectory(dir);

                    // Now write the config and the cleaned up log to it
                    try
                    {
                        using (StreamWriter sw = File.AppendText(path))
                        {
                            sw.Write("Debug information for CONTRACT_TYPE '" + name + "':\n");
                            sw.Write("\nConfiguration:\n");
                            sw.Write(config);
                            sw.Write("\nData Nodes:\n");
                            sw.Write(DataNodeDebug(dataNode));
                            sw.Write("\nOutput log:\n");
                            sw.Write(log);
                        }
                    }
                    catch
                    {
                        LoggingUtil.LogError(this, "Exception while attempting to write to the file: " + path);
                    }
                }

                return(valid);
            }
            catch (Exception e)
            {
                enabled = false;
                throw new Exception("Error loading CONTRACT_TYPE '" + name + "'", e);
            }
            finally
            {
                LoggingUtil.CaptureLog = false;
                LoggingUtil.logLevel   = origLogLevel;
                loaded = true;
            }
        }