internal IEnumerable <Hex> GetNeighbours(int x, int y, bool passable = true) { // Debug.Log (String.Format("bonvoyage - finding neighbours for {0}, {1}", x, y)); var tile = tiles.Find(t => (t.X == x) && (t.Y == y)); if (tile == null) { // Debug.Log ("bonvoyage - tile not found"); return(null); } List <Hex> neighbours = new List <Hex> (); foreach (var direction in directions) { int dirX = direction.Value.X; int dirY = direction.Value.Y; var neighbour = tiles.Find(n => (n.X == tile.X + dirX) && (n.Y == tile.Y + dirY)); if (neighbour == null) { // Debug.Log ("bonvoyage - neighbour not found"); double[] coords = GeoUtils.GetLatitudeLongitude(tile.Latitude, tile.Longitude, tile.Bearing + direction.Key, StepSize, mainBody.Radius); double newBearing = GeoUtils.FinalBearing(tile.Latitude, tile.Longitude, coords [0], coords [1]); newBearing = (newBearing - direction.Key + 360) % 360; double altitude = GeoUtils.TerrainHeightAt(coords [0], coords [1], mainBody); neighbour = new Hex(coords [0], coords [1], altitude, newBearing, tile.X + dirX, tile.Y + dirY, this); } neighbours.Add(neighbour); tiles.Add(neighbour); } if (passable) { return(neighbours.Where( n => (n.Altitude >= 0 || !mainBody.ocean) && ((n.Altitude - tile.Altitude) < StepSize / 2) && ((n.Altitude - tile.Altitude) > 0 - StepSize / 2) )); } else { return(neighbours); } }
/// <summary> /// Prevent crazy torpedoing active vessel :D /// </summary> /// <returns><c>true</c>, if rover was moved, <c>false</c> otherwise.</returns> /// <param name="latitude">Latitude.</param> /// <param name="longitude">Longitude.</param> private bool MoveSafe(double latitude, double longitude) { double altitude = GeoUtils.TerrainHeightAt(latitude, longitude, vessel.mainBody); if (FlightGlobals.ActiveVessel != null) { Vector3d newPos = vessel.mainBody.GetWorldSurfacePosition(latitude, longitude, altitude); Vector3d actPos = FlightGlobals.ActiveVessel.GetWorldPos3D(); double distance = Vector3d.Distance(newPos, actPos); if (distance <= 2400) { return(false); } } vessel.latitude = latitude; vessel.longitude = longitude; vessel.altitude = altitude + vessel.heightFromTerrain; return(true); }
public void FindPath() { double distanceToTarget = GeoUtils.GetDistance(startLatitude, startLongitude, targetLatitude, targetLongitude, mainBody.Radius); if (distanceToTarget < 1000) { return; } double bearing = GeoUtils.InitialBearing(startLatitude, startLongitude, targetLatitude, targetLongitude); double altitude = GeoUtils.TerrainHeightAt(startLatitude, startLongitude, mainBody); int x = 0; int y = 0; Hex start = new Hex(startLatitude, startLongitude, altitude, bearing, x, y, this); tiles.Add(start); double straightPath = 0; // ScreenMessages.PostScreenMessage ("building straight " + DateTime.Now.ToString()); while (straightPath < distanceToTarget - 500) { GetNeighbours(x, y, false); x += directions [0].X; y += directions [0].Y; straightPath += 1000; } Hex destination = tiles.Find(t => (t.X == x + directions [180].X) && (t.Y == y + directions [180].Y)); /* KSP.IO.File.AppendAllText<BonVoyage> ( * // String.Format("lat: {0}\nlon: {1}\nbea: {2}\n----\n", this.latitude, this.longitude, this.bearing), * String.Format("start: {0}, destination: {1}\n----\n", start.Id, destination.Id), * "path" * );*/ // ScreenMessages.PostScreenMessage ("started caclulation " + DateTime.Now.ToString()); path = Path <Hex> .FindPath <Hex> (start, destination, distance, estimate); ScreenMessages.PostScreenMessage("Path build"); }
public void SetToActive() { if (this.vessel.targetObject == null || this.vessel.situation != Vessel.Situations.LANDED) { return; } Vessel targetVessel = this.vessel.targetObject.GetVessel(); if (targetVessel == null) { ScreenMessages.PostScreenMessage("Target some suitable vessel first!"); return; } if (targetVessel.mainBody == this.vessel.mainBody && targetVessel.situation == Vessel.Situations.LANDED) { Deactivate(); this.distanceToTarget = GeoUtils.GetDistance( this.vessel.latitude, this.vessel.longitude, targetVessel.latitude, targetVessel.longitude, this.vessel.mainBody.Radius ); double bearing = GeoUtils.InitialBearing(this.vessel.latitude, this.vessel.longitude, targetVessel.latitude, targetVessel.longitude); // We don't want to spawn inside vessel if (distanceToTarget == 0) { return; } this.distanceToTarget -= 200; double[] newCoordinates = GeoUtils.GetLatitudeLongitude(this.vessel.latitude, this.vessel.longitude, bearing, distanceToTarget, this.vessel.mainBody.Radius); this.targetLatitude = newCoordinates[0]; this.targetLongitude = newCoordinates[1]; this.distanceTravelled = 0; FindPath(); } else { ScreenMessages.PostScreenMessage("Your target is out there somewhere, this won't work!"); } }
/// <summary> /// Prevent crazy torpedoing active vessel :D /// </summary> /// <returns><c>true</c>, if rover was moved, <c>false</c> otherwise.</returns> /// <param name="latitude">Latitude.</param> /// <param name="longitude">Longitude.</param> private bool MoveSafe(double latitude, double longitude) { double altitude = GeoUtils.TerrainHeightAt(latitude, longitude, vessel.mainBody); if (FlightGlobals.ActiveVessel != null) { Vector3d newPos = vessel.mainBody.GetWorldSurfacePosition(latitude, longitude, altitude); Vector3d actPos = FlightGlobals.ActiveVessel.GetWorldPos3D(); double distance = Vector3d.Distance(newPos, actPos); if (distance <= 2400) { return(false); } // VesselRanges ranges = active.vesselRanges.GetSituationRanges(Vessel.Situations.LANDED || Vessel.Situations.FLYING); // vessel.GoOffRails (); // vessel.Load (); } vessel.latitude = latitude; vessel.longitude = longitude; vessel.altitude = altitude; return(true); }
//[KSPEvent(guiActive = true, guiName = "Set to active target")] public void SetToActive() { if (this.vessel.targetObject == null || this.vessel.situation != Vessel.Situations.LANDED) { return; } Vessel targetVessel = this.vessel.targetObject.GetVessel(); if (targetVessel == null) { ScreenMessages.PostScreenMessage("Target some suitable vessel first!"); return; } if (targetVessel.mainBody == this.vessel.mainBody && targetVessel.situation == Vessel.Situations.LANDED) { Deactivate(); double[] newCoordinates = GeoUtils.StepBack( this.vessel.latitude, this.vessel.longitude, targetVessel.latitude, targetVessel.longitude, this.vessel.mainBody.Radius, 200 ); this.targetLatitude = newCoordinates[0]; this.targetLongitude = newCoordinates[1]; this.distanceTravelled = 0; FindPath(); } else { ScreenMessages.PostScreenMessage("Your target is out there somewhere, this won't work!"); } }
/// <summary> /// Update rover. /// </summary> /// <param name="currentTime">Current time.</param> public void Update(double currentTime) { status2 = ""; if (vessel.isActiveVessel) { status = "current"; return; } if (!bvActive || vessel.loaded) { status = "idle"; return; } Vector3d vesselPos = vessel.mainBody.position - vessel.GetWorldPos3D(); Vector3d toKerbol = vessel.mainBody.position - FlightGlobals.Bodies[0].position; //double angle = Vector3d.Angle(vesselPos, toKerbol); angle = Vector3d.Angle(vesselPos, toKerbol); // Speed penalties at twighlight and at night if (angle > 90 && isManned) { speedMultiplier = 0.25; status2 = " (night)"; } else if (angle > 85 && isManned) { speedMultiplier = 0.5; status2 = " (twilight)"; } else if (angle > 80 && isManned) { speedMultiplier = 0.75; status2 = " (twilight)"; } else { speedMultiplier = 1.0; } // No moving at night, or when there's not enougth solar light for solar powered rovers //if (angle > 90 && solarPowered) // No moving at night, if there isn't power source if ((angle > 90) && (averageSpeedAtNight == 0.0)) { status = "awaiting sunlight"; lastTime = currentTime; BVModule.SetValue("lastTime", currentTime.ToString()); return; } double deltaT = currentTime - lastTime; double deltaS = AverageSpeed * deltaT; double bearing = GeoUtils.InitialBearing( vessel.latitude, vessel.longitude, targetLatitude, targetLongitude ); distanceTravelled += deltaS; if (distanceTravelled >= distanceToTarget) { if (!MoveSafe(targetLatitude, targetLongitude)) { distanceTravelled -= deltaS; } else { distanceTravelled = distanceToTarget; bvActive = false; BVModule.SetValue("isActive", "False"); BVModule.SetValue("distanceTravelled", distanceToTarget.ToString()); BVModule.SetValue("pathEncoded", ""); if (BonVoyage.Instance.AutoDewarp) { if (TimeWarp.CurrentRate > 3) { TimeWarp.SetRate(3, true); } if (TimeWarp.CurrentRate > 0) { TimeWarp.SetRate(0, false); } ScreenMessages.PostScreenMessage(vessel.vesselName + " has arrived to destination at " + vessel.mainBody.bodyDisplayName.Replace("^N", "")); } HoneyImHome(); } status = "idle"; } else { try // There is sometimes exception during scene change to flight scene { int step = Convert.ToInt32(Math.Floor(distanceTravelled / PathFinder.StepSize)); double remainder = distanceTravelled % PathFinder.StepSize; if (step < path.Count - 1) { bearing = GeoUtils.InitialBearing( path[step].latitude, path[step].longitude, path[step + 1].latitude, path[step + 1].longitude ); } else { bearing = GeoUtils.InitialBearing( path[step].latitude, path[step].longitude, targetLatitude, targetLongitude ); } double[] newCoordinates = GeoUtils.GetLatitudeLongitude( path[step].latitude, path[step].longitude, bearing, remainder, vessel.mainBody.Radius ); if (!MoveSafe(newCoordinates[0], newCoordinates[1])) { distanceTravelled -= deltaS; status = "idle"; } else { status = "roving"; } } catch { }; } Save(currentTime); }
/// <summary> /// Update vessel /// </summary> /// <param name="currentTime"></param> internal override void Update(double currentTime) { if (vessel == null) { return; } if (vessel.isActiveVessel) { lastTimeUpdated = 0; if (active) { ScreenMessages.PostScreenMessage(Localizer.Format("#LOC_BV_AutopilotActive"), 10f).color = Color.red; } return; } if (!active || vessel.loaded) { return; } // If we don't know the last time of update, then set it and wait for the next update cycle if (lastTimeUpdated == 0) { State = VesselState.Idle; lastTimeUpdated = currentTime; BVModule.SetValue("lastTimeUpdated", currentTime.ToString()); return; } double deltaT = currentTime - lastTimeUpdated; // Time delta from the last update double deltaS = AverageSpeed * deltaT; // Distance delta from the last update distanceTravelled += deltaS; if (distanceTravelled >= distanceToTarget) // We reached the target { if (!MoveSafely(targetLatitude, targetLongitude)) { distanceTravelled -= deltaS; } else { distanceTravelled = distanceToTarget; active = false; arrived = true; BVModule.SetValue("active", "False"); BVModule.SetValue("arrived", "True"); BVModule.SetValue("distanceTravelled", distanceToTarget.ToString()); BVModule.SetValue("pathEncoded", ""); // Dewarp if (Configuration.AutomaticDewarp) { if (TimeWarp.CurrentRate > 3) // Instant drop to 50x warp { TimeWarp.SetRate(3, true); } if (TimeWarp.CurrentRate > 0) // Gradual drop out of warp { TimeWarp.SetRate(0, false); } ScreenMessages.PostScreenMessage(vessel.vesselName + " " + Localizer.Format("#LOC_BV_VesselArrived") + " " + vessel.mainBody.bodyDisplayName.Replace("^N", ""), 5f); } NotifyArrival(); } State = VesselState.Idle; } else { try // There is sometimes null ref exception during scene change { int step = Convert.ToInt32(Math.Floor(distanceTravelled / PathFinder.StepSize)); // In which step of the path we are double remainder = distanceTravelled % PathFinder.StepSize; // Current remaining distance from the current step double bearing = 0; if (step < path.Count - 1) { bearing = GeoUtils.InitialBearing( // Bearing to the next step from previous step path[step].latitude, path[step].longitude, path[step + 1].latitude, path[step + 1].longitude ); } else { bearing = GeoUtils.InitialBearing( // Bearing to the target from previous step path[step].latitude, path[step].longitude, targetLatitude, targetLongitude ); } // Compute new coordinates, we are moving from the current step, distance is "remainder" double[] newCoordinates = GeoUtils.GetLatitudeLongitude( path[step].latitude, path[step].longitude, bearing, remainder, vessel.mainBody.Radius ); // Move if (!MoveSafely(newCoordinates[0], newCoordinates[1])) { distanceTravelled -= deltaS; State = VesselState.Idle; } else { State = VesselState.Moving; } } catch { } } Save(currentTime); }
/// <summary> /// Update rover. /// </summary> /// <param name="currentTime">Current time.</param> public void Update(double currentTime) { if (vessel.isActiveVessel) { status = "current"; return; } if (!bvActive || vessel.loaded) { status = "idle"; return; } Vector3d vesselPos = vessel.mainBody.position - vessel.GetWorldPos3D(); Vector3d toKerbol = vessel.mainBody.position - FlightGlobals.Bodies[0].position; double angle = Vector3d.Angle(vesselPos, toKerbol); // Speed penalties at twighlight and at night if (angle > 90 && isManned) { speedMultiplier = 0.25; } else if (angle > 85 && isManned) { speedMultiplier = 0.5; } else if (angle > 80 && isManned) { speedMultiplier = 0.75; } else { speedMultiplier = 1.0; } // No moving at night, or when there's not enougth solar light for solar powered rovers if (angle > 90 && solarPowered) { status = "awaiting sunlight"; lastTime = currentTime; BVModule.SetValue("lastTime", currentTime.ToString()); vessel.protoVessel = new ProtoVessel(vesselConfigNode, HighLogic.CurrentGame); return; } double deltaT = currentTime - lastTime; double deltaS = AverageSpeed * deltaT; double bearing = GeoUtils.InitialBearing( vessel.latitude, vessel.longitude, targetLatitude, targetLongitude ); distanceTravelled += deltaS; if (distanceTravelled >= distanceToTarget) { // vessel.latitude = targetLatitude; // vessel.longitude = targetLongitude; if (!MoveSafe(targetLatitude, targetLongitude)) { distanceTravelled -= deltaS; } else { distanceTravelled = distanceToTarget; bvActive = false; BVModule.SetValue("isActive", "False"); BVModule.SetValue("distanceTravelled", distanceToTarget.ToString()); BVModule.SetValue("pathEncoded", ""); // BVModule.GetNode ("EVENTS").GetNode ("Activate").SetValue ("active", "True"); // BVModule.GetNode ("EVENTS").GetNode ("Deactivate").SetValue ("active", "False"); if (BonVoyage.Instance.AutoDewarp) { if (TimeWarp.CurrentRate > 3) { TimeWarp.SetRate(3, true); } if (TimeWarp.CurrentRate > 0) { TimeWarp.SetRate(0, false); } ScreenMessages.PostScreenMessage(vessel.vesselName + " has arrived to destination at " + vessel.mainBody.name); } HoneyImHome(); } status = "idle"; } else { int step = Convert.ToInt32(Math.Floor(distanceTravelled / PathFinder.StepSize)); double remainder = distanceTravelled % PathFinder.StepSize; if (step < path.Count - 1) { bearing = GeoUtils.InitialBearing( path[step].latitude, path[step].longitude, path[step + 1].latitude, path[step + 1].longitude ); } else { bearing = GeoUtils.InitialBearing( path[step].latitude, path[step].longitude, targetLatitude, targetLongitude ); } double[] newCoordinates = GeoUtils.GetLatitudeLongitude( path[step].latitude, path[step].longitude, bearing, remainder, vessel.mainBody.Radius ); // vessel.latitude = newCoordinates[0]; // vessel.longitude = newCoordinates[1]; if (!MoveSafe(newCoordinates [0], newCoordinates [1])) { distanceTravelled -= deltaS; status = "idle"; } else { status = "roving"; } } // vessel.altitude = GeoUtils.TerrainHeightAt(vessel.latitude, vessel.longitude, vessel.mainBody); Save(currentTime); }
public void Update() { if (lastUpdated.AddSeconds(1) > DateTime.Now) { return; } lastUpdated = DateTime.Now; double currentTime = Planetarium.GetUniversalTime(); foreach (var rover in activeRovers) { if (rover.vessel.isActiveVessel) { rover.status = "current"; continue; } if (!rover.bvActive || rover.vessel.loaded) { rover.status = "idle"; continue; } Vector3d vesselPos = rover.vessel.mainBody.position - rover.vessel.GetWorldPos3D(); Vector3d toKerbol = rover.vessel.mainBody.position - FlightGlobals.Bodies[0].position; double angle = Vector3d.Angle(vesselPos, toKerbol); // No moving at night, or when there's not enougth solar light if (angle >= 85 && rover.solarPowered) { rover.status = "awaiting sunlight"; rover.lastTime = currentTime; rover.BVModule.SetValue("lastTime", currentTime.ToString()); rover.vessel.protoVessel = new ProtoVessel(rover.vesselConfigNode, HighLogic.CurrentGame); continue; } double deltaT = currentTime - rover.lastTime; double deltaS = rover.averageSpeed * deltaT; double bearing = GeoUtils.InitialBearing( rover.vessel.latitude, rover.vessel.longitude, rover.targetLatitude, rover.targetLongitude ); rover.distanceTravelled += deltaS; if (rover.distanceTravelled >= rover.distanceToTarget) { rover.distanceTravelled = rover.distanceToTarget; rover.vessel.latitude = rover.targetLatitude; rover.vessel.longitude = rover.targetLongitude; rover.bvActive = false; rover.BVModule.SetValue("isActive", "False"); rover.BVModule.SetValue("distanceTravelled", rover.distanceToTarget.ToString()); rover.BVModule.GetNode("EVENTS").GetNode("Activate").SetValue("active", "True"); rover.BVModule.GetNode("EVENTS").GetNode("Deactivate").SetValue("active", "False"); if (autoDewarp) { TimeWarp.SetRate(0, false); ScreenMessages.PostScreenMessage(rover.vessel.vesselName + " has arrived to destination at " + rover.vessel.mainBody.name); } MessageSystem.Message message = new MessageSystem.Message( "Rover arrived", //------------------------------------------ rover.vessel.vesselName + " has arrived to destination\nLAT:" + rover.targetLatitude.ToString("F2") + "\nLON:" + rover.targetLongitude.ToString("F2") + "\nAt " + rover.vessel.mainBody.name + ". \n" + "Distance travelled: " + rover.distanceTravelled.ToString("N") + " meters", //------------------------------------------ MessageSystemButton.MessageButtonColor.GREEN, MessageSystemButton.ButtonIcons.COMPLETE ); MessageSystem.Instance.AddMessage(message); rover.status = "idle"; } else { int step = Convert.ToInt32(Math.Floor(rover.distanceTravelled / 1000)); double remainder = rover.distanceTravelled % 1000; if (step < rover.path.Count - 1) { bearing = GeoUtils.InitialBearing( rover.path[step].latitude, rover.path[step].longitude, rover.path[step + 1].latitude, rover.path[step + 1].longitude ); } else { bearing = GeoUtils.InitialBearing( rover.path[step].latitude, rover.path[step].longitude, rover.targetLatitude, rover.targetLongitude ); } double[] newCoordinates = GeoUtils.GetLatitudeLongitude( rover.path[step].latitude, rover.path[step].longitude, bearing, remainder, rover.vessel.mainBody.Radius ); rover.vessel.latitude = newCoordinates[0]; rover.vessel.longitude = newCoordinates[1]; rover.status = "roving"; } rover.vessel.altitude = GeoUtils.TerrainHeightAt(rover.vessel.latitude, rover.vessel.longitude, rover.vessel.mainBody); // rover.toTravel = rover.distanceToTarget - rover.distanceTravelled; rover.lastTime = currentTime; // Save data to protovessel rover.vesselConfigNode.SetValue("lat", rover.vessel.latitude.ToString()); rover.vesselConfigNode.SetValue("lon", rover.vessel.longitude.ToString()); rover.vesselConfigNode.SetValue("alt", rover.vessel.altitude.ToString()); rover.vesselConfigNode.SetValue("landedAt", rover.vessel.mainBody.theName); rover.BVModule.SetValue("distanceTravelled", (rover.distanceTravelled).ToString()); rover.BVModule.SetValue("lastTime", currentTime.ToString()); rover.vessel.protoVessel = new ProtoVessel(rover.vesselConfigNode, HighLogic.CurrentGame); } }
private double Estimate(Hex hex) { return(GeoUtils.GetDistance(hex.Latitude, hex.Longitude, targetLatitude, targetLongitude, mainBody.Radius)); }
/// <summary> /// Update vessel /// </summary> /// <param name="currentTime"></param> internal override void Update(double currentTime) { if (vessel == null) { return; } if (vessel.isActiveVessel) { lastTimeUpdated = 0; if (active) { ScreenMessages.PostScreenMessage(Localizer.Format("#LOC_BV_AutopilotActive"), 10f).color = Color.red; } return; } if (!active || vessel.loaded) { return; } // If we don't know the last time of update, then set it and wait for the next update cycle if (lastTimeUpdated == 0) { State = VesselState.Idle; lastTimeUpdated = currentTime; BVModule.SetValue("lastTimeUpdated", currentTime.ToString()); return; } Vector3d roverPos = vessel.mainBody.position - vessel.GetWorldPos3D(); Vector3d toMainStar = vessel.mainBody.position - FlightGlobals.Bodies[mainStarIndex].position; angle = Vector3d.Angle(roverPos, toMainStar); // Angle between rover and the main star // Speed penalties at twighlight and at night if ((angle > 90) && manned) // night { speedMultiplier = 0.25; } else if ((angle > 85) && manned) // twilight { speedMultiplier = 0.5; } else if ((angle > 80) && manned) // twilight { speedMultiplier = 0.75; } else // day { speedMultiplier = 1.0; } // No moving at night, if there isn't enough power if ((angle > 90) && (averageSpeedAtNight == 0.0)) { State = VesselState.AwaitingSunlight; lastTimeUpdated = currentTime; BVModule.SetValue("lastTimeUpdated", currentTime.ToString()); return; } double deltaT = currentTime - lastTimeUpdated; double deltaS = AverageSpeed * deltaT; distanceTravelled += deltaS; if (distanceTravelled >= distanceToTarget) // We reached the target { if (!MoveSafely(targetLatitude, targetLongitude)) { distanceTravelled -= deltaS; } else { distanceTravelled = distanceToTarget; active = false; arrived = true; BVModule.SetValue("active", "False"); BVModule.SetValue("arrived", "True"); BVModule.SetValue("distanceTravelled", distanceToTarget.ToString()); BVModule.SetValue("pathEncoded", ""); // Dewarp if (Configuration.AutomaticDewarp) { if (TimeWarp.CurrentRate > 3) // Instant drop to 50x warp { TimeWarp.SetRate(3, true); } if (TimeWarp.CurrentRate > 0) // Gradual drop out of warp { TimeWarp.SetRate(0, false); } ScreenMessages.PostScreenMessage(vessel.vesselName + " " + Localizer.Format("#LOC_BV_VesselArrived") + " " + vessel.mainBody.bodyDisplayName.Replace("^N", ""), 5f); } NotifyArrival(); } State = VesselState.Idle; } else { try // There is sometimes null ref exception during scene change { int step = Convert.ToInt32(Math.Floor(distanceTravelled / PathFinder.StepSize)); // In which step of the path we are double remainder = distanceTravelled % PathFinder.StepSize; // Current remaining distance from the current step double bearing = 0; if (step < path.Count - 1) { bearing = GeoUtils.InitialBearing( // Bearing to the next step from previous step path[step].latitude, path[step].longitude, path[step + 1].latitude, path[step + 1].longitude ); } else { bearing = GeoUtils.InitialBearing( // Bearing to the target from previous step path[step].latitude, path[step].longitude, targetLatitude, targetLongitude ); } // Compute new coordinates, we are moving from the current step, distance is "remainder" double[] newCoordinates = GeoUtils.GetLatitudeLongitude( path[step].latitude, path[step].longitude, bearing, remainder, vessel.mainBody.Radius ); // Move if (!MoveSafely(newCoordinates[0], newCoordinates[1])) { distanceTravelled -= deltaS; State = VesselState.Idle; } else { State = VesselState.Moving; } } catch { } } Save(currentTime); }
/// <summary> /// Update vessel /// </summary> /// <param name="currentTime"></param> internal override void Update(double currentTime) { if (vessel == null) { return; } if (vessel.isActiveVessel) { lastTimeUpdated = 0; if (active) { ScreenMessages.PostScreenMessage(Localizer.Format("#LOC_BV_AutopilotActive"), 10f).color = Color.red; } return; } if (!active || vessel.loaded) { return; } // If we don't know the last time of update, then set it and wait for the next update cycle if (lastTimeUpdated == 0) { State = VesselState.Idle; lastTimeUpdated = currentTime; BVModule.SetValue("lastTimeUpdated", currentTime.ToString()); return; } Vector3d roverPos = vessel.mainBody.position - vessel.GetWorldPos3D(); Vector3d toMainStar = vessel.mainBody.position - FlightGlobals.Bodies[mainStarIndex].position; angle = Vector3d.Angle(roverPos, toMainStar); // Angle between rover and the main star // Speed penalties at twighlight and at night if ((angle > 90) && manned) // night { speedMultiplier = 0.25; } else if ((angle > 85) && manned) // twilight { speedMultiplier = 0.5; } else if ((angle > 80) && manned) // twilight { speedMultiplier = 0.75; } else // day { speedMultiplier = 1.0; } double deltaT = currentTime - lastTimeUpdated; // Time delta from the last update double deltaTOver = 0; // deltaT which is calculated from a value over the maximum resource amout available // Compute increase or decrease in EC from the last update if (!CheatOptions.InfiniteElectricity && batteries.UseBatteries && !DetectKerbalism.Found()) { // Process fuel cells before batteries if (!CheatOptions.InfinitePropellant && fuelCells.Use && ((angle > 90) || (batteries.ECPerSecondGenerated - fuelCells.OutputValue <= 0) || (batteries.CurrentEC < batteries.MaxUsedEC))) // Night, not enough solar power or we need to recharge batteries { if (!((angle > 90) && (batteries.CurrentEC == 0))) // Don't use fuel cells, if it's night and current EC of batteries is zero. This means, that there isn't enough power to recharge them and fuel is wasted. { var iList = fuelCells.InputResources; for (int i = 0; i < iList.Count; i++) { iList[i].CurrentAmountUsed += iList[i].Ratio * deltaT; if (iList[i].CurrentAmountUsed > iList[i].MaximumAmountAvailable) { deltaTOver = Math.Max(deltaTOver, (iList[i].CurrentAmountUsed - iList[i].MaximumAmountAvailable) / iList[i].Ratio); } } if (deltaTOver > 0) { deltaT -= deltaTOver; // Reduce the amount of used resources for (int i = 0; i < iList.Count; i++) { iList[i].CurrentAmountUsed -= iList[i].Ratio * deltaTOver; } } } } if (angle <= 90) // day { batteries.CurrentEC = Math.Min(batteries.CurrentEC + batteries.ECPerSecondGenerated * deltaT, batteries.MaxUsedEC); } else // night { batteries.CurrentEC = Math.Max(batteries.CurrentEC - batteries.ECPerSecondConsumed * deltaT, 0); } } // No moving at night, if there isn't enough power if ((angle > 90) && (averageSpeedAtNight == 0.0) && !(batteries.UseBatteries && (batteries.CurrentEC > 0))) { State = VesselState.AwaitingSunlight; lastTimeUpdated = currentTime; BVModule.SetValue("lastTimeUpdated", currentTime.ToString()); return; } double deltaS = AverageSpeed * deltaT; // Distance delta from the last update distanceTravelled += deltaS; if (distanceTravelled >= distanceToTarget) // We reached the target { if (!MoveSafely(targetLatitude, targetLongitude)) { distanceTravelled -= deltaS; } else { distanceTravelled = distanceToTarget; active = false; arrived = true; BVModule.SetValue("active", "False"); BVModule.SetValue("arrived", "True"); BVModule.SetValue("distanceTravelled", distanceToTarget.ToString()); BVModule.SetValue("pathEncoded", ""); // Dewarp if (Configuration.AutomaticDewarp) { if (TimeWarp.CurrentRate > 3) // Instant drop to 50x warp { TimeWarp.SetRate(3, true); } if (TimeWarp.CurrentRate > 0) // Gradual drop out of warp { TimeWarp.SetRate(0, false); } ScreenMessages.PostScreenMessage(vessel.vesselName + " " + Localizer.Format("#LOC_BV_VesselArrived") + " " + vessel.mainBody.bodyDisplayName.Replace("^N", ""), 5f); } NotifyArrival(); } State = VesselState.Idle; } else { try // There is sometimes null ref exception during scene change { int step = Convert.ToInt32(Math.Floor(distanceTravelled / PathFinder.StepSize)); // In which step of the path we are double remainder = distanceTravelled % PathFinder.StepSize; // Current remaining distance from the current step double bearing = 0; if (step < path.Count - 1) { bearing = GeoUtils.InitialBearing( // Bearing to the next step from previous step path[step].latitude, path[step].longitude, path[step + 1].latitude, path[step + 1].longitude ); } else { bearing = GeoUtils.InitialBearing( // Bearing to the target from previous step path[step].latitude, path[step].longitude, targetLatitude, targetLongitude ); } // Compute new coordinates, we are moving from the current step, distance is "remainder" double[] newCoordinates = GeoUtils.GetLatitudeLongitude( path[step].latitude, path[step].longitude, bearing, remainder, vessel.mainBody.Radius ); // Move if (!MoveSafely(newCoordinates[0], newCoordinates[1])) { distanceTravelled -= deltaS; State = VesselState.Idle; } else { State = VesselState.Moving; } } catch { } } Save(currentTime); // Stop the rover, we don't have enough of fuel if (deltaTOver > 0 || (!CheatOptions.InfiniteElectricity && batteries.UseBatteries && batteries.CurrentEC <= 0.1)) { active = false; arrived = true; BVModule.SetValue("active", "False"); BVModule.SetValue("arrived", "True"); BVModule.SetValue("pathEncoded", ""); // Dewarp if (Configuration.AutomaticDewarp) { if (TimeWarp.CurrentRate > 3) // Instant drop to 50x warp { TimeWarp.SetRate(3, true); } if (TimeWarp.CurrentRate > 0) // Gradual drop out of warp { TimeWarp.SetRate(0, false); } ScreenMessages.PostScreenMessage(vessel.vesselName + " " + Localizer.Format("#LOC_BV_Warning_Stopped") + ".", 5f).color = Color.red; } if (!CheatOptions.InfiniteElectricity && batteries.UseBatteries && batteries.CurrentEC <= 0.1) { NotifyBatteryEmpty(); } else { NotifyNotEnoughFuel(); } State = VesselState.Idle; } }