void UpdatePosition() { Vector3d oceanNormal = _vessel.mainBody.GetSurfaceNVector(_vessel.latitude, _vessel.longitude); Vector3 newPosition = (_vessel.ReferenceTransform.position - oceanNormal * (FlightGlobals.getAltitudeAtPos(_vessel.ReferenceTransform.position) - fColliderHeight)); _collider.rigidbody.position = newPosition; _collider.rigidbody.rotation = Quaternion.LookRotation(oceanNormal) * Quaternion.AngleAxis(90f, Vector3.right); }
private void UpdateMove() { if (!MovingVessel) { EndMove(); return; } MovingVessel.IgnoreGForces(240); // Lerp is animating move if (!_hoverChanged) { MoveHeight = Mathf.Lerp(MoveHeight, _vBounds.BottomLength + HoverHeight, 10 * Time.fixedDeltaTime); } else { double alt = MovingVessel.radarAltitude; // sINCE Lerp is animating move from 0 to hoverheight, we do not want this going below current altitude if (MoveHeight < alt) { MoveHeight = Convert.ToSingle(alt); } MoveHeight = MovingVessel.Splashed ? Mathf.Lerp(MoveHeight, _vBounds.BottomLength + _hoverAdjust, 10 * Time.fixedDeltaTime) : Mathf.Lerp(MoveHeight, _vBounds.BottomLength + (MoveHeight + _hoverAdjust < 0 ? -MoveHeight : _hoverAdjust), 10 * Time.fixedDeltaTime); } MovingVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, false); _up = (MovingVessel.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; Vector3 forward; if (MapView.MapIsEnabled) { forward = North(); } else { forward = Vector3.ProjectOnPlane(MovingVessel.CoM - FlightCamera.fetch.mainCamera.transform.position, _up).normalized; if (Vector3.Dot(-_up, FlightCamera.fetch.mainCamera.transform.up) > 0) { forward = Vector3.ProjectOnPlane(FlightCamera.fetch.mainCamera.transform.up, _up).normalized; } } Vector3 right = Vector3.Cross(_up, forward); Vector3 offsetDirection = Vector3.zero; bool inputting = false; //Altitude Adjustment if (GameSettings.THROTTLE_CUTOFF.GetKey()) { _hoverAdjust = 0f; _hoverChanged = false; } if (GameSettings.THROTTLE_UP.GetKey()) { _hoverAdjust += MoveSpeed * Time.fixedDeltaTime; inputting = true; _hoverChanged = true; } if (GameSettings.THROTTLE_DOWN.GetKey()) { _hoverAdjust += -(MoveSpeed * Time.fixedDeltaTime); inputting = true; _hoverChanged = true; } if (GameSettings.PITCH_DOWN.GetKey()) { offsetDirection += (forward * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.PITCH_UP.GetKey()) { offsetDirection += (-forward * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.YAW_RIGHT.GetKey()) { offsetDirection += (right * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.YAW_LEFT.GetKey()) { offsetDirection += (-right * MoveSpeed * Time.fixedDeltaTime); inputting = true; } if (GameSettings.TRANSLATE_RIGHT.GetKey()) { _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.forward) * _startRotation; _hasRotated = true; } else if (GameSettings.TRANSLATE_LEFT.GetKey()) { _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.forward) * _startRotation; _hasRotated = true; } if (GameSettings.TRANSLATE_DOWN.GetKey()) { _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.right) * _startRotation; _hasRotated = true; } else if (GameSettings.TRANSLATE_UP.GetKey()) { _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.right) * _startRotation; _hasRotated = true; } if (GameSettings.ROLL_LEFT.GetKey()) { _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.up) * _startRotation; _hasRotated = true; } else if (GameSettings.ROLL_RIGHT.GetKey()) { _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.up) * _startRotation; _hasRotated = true; } //auto level plane if (GameSettings.TRANSLATE_FWD.GetKey()) { Quaternion targetRot = Quaternion.LookRotation(-_up, forward); _startRotation = Quaternion.RotateTowards(_startRotation, targetRot, RotationSpeed * 2); _hasRotated = true; } else if (GameSettings.TRANSLATE_BACK.GetKey())//auto level rocket { Quaternion targetRot = Quaternion.LookRotation(forward, _up); _startRotation = Quaternion.RotateTowards(_startRotation, targetRot, RotationSpeed * 2); _hasRotated = true; } if (inputting) { _currMoveSpeed = Mathf.Clamp(Mathf.MoveTowards(_currMoveSpeed, MoveSpeed, MoveAccel * Time.fixedDeltaTime), 0, MoveSpeed); } else { _currMoveSpeed = 0; } Vector3 offset = offsetDirection.normalized * _currMoveSpeed; _currMoveVelocity = offset / Time.fixedDeltaTime; Vector3 vSrfPt = MovingVessel.CoM - (MoveHeight * _up); bool srfBelowWater = false; RaycastHit ringHit; bool surfaceDetected = CapsuleCast(out ringHit); Vector3 finalOffset = Vector3.zero; if (surfaceDetected) { if (FlightGlobals.getAltitudeAtPos(ringHit.point) < 0) { srfBelowWater = true; } Vector3 rOffset = Vector3.Project(ringHit.point - vSrfPt, _up); Vector3 mOffset = (vSrfPt + offset) - MovingVessel.CoM; finalOffset = rOffset + mOffset + (MoveHeight * _up); MovingVessel.Translate(finalOffset); } PQS bodyPQS = MovingVessel.mainBody.pqsController; Vector3d geoCoords = WorldPositionToGeoCoords(MovingVessel.GetWorldPos3D() + (_currMoveVelocity * Time.fixedDeltaTime), MovingVessel.mainBody); double lat = geoCoords.x; double lng = geoCoords.y; Vector3d bodyUpVector = new Vector3d(1, 0, 0); bodyUpVector = QuaternionD.AngleAxis(lat, Vector3d.forward /*around Z axis*/) * bodyUpVector; bodyUpVector = QuaternionD.AngleAxis(lng, Vector3d.down /*around -Y axis*/) * bodyUpVector; double srfHeight = bodyPQS.GetSurfaceHeight(bodyUpVector); //double alt = srfHeight - bodyPQS.radius; //double rAlt = movingVessel.radarAltitude; //double tAlt = TrueAlt(movingVessel); //double pAlt = movingVessel.pqsAltitude; //double teralt = movingVessel.mainBody.TerrainAltitude(movingVessel.mainBody.GetLatitude(geoCoords), movingVessel.mainBody.GetLongitude(geoCoords)); //Debug.Log ("Surface height: "+movingVessel.mainBody.pqsController.GetSurfaceHeight(up)); if (!surfaceDetected || srfBelowWater) { Vector3 terrainPos = MovingVessel.mainBody.position + (float)srfHeight * _up; Vector3 waterSrfPoint = FlightGlobals.currentMainBody.position + ((float)FlightGlobals.currentMainBody.Radius * _up); if (!surfaceDetected) { MovingVessel.SetPosition(terrainPos + (MoveHeight * _up) + offset); } else { MovingVessel.SetPosition(waterSrfPoint + (MoveHeight * _up) + offset); } //update vessel situation to splashed down: MovingVessel.UpdateLandedSplashed(); } //fix surface rotation Quaternion srfRotFix = Quaternion.FromToRotation(_startingUp, _up); _currRotation = srfRotFix * _startRotation; MovingVessel.SetRotation(_currRotation); if (Vector3.Angle(_startingUp, _up) > 5) { _startRotation = _currRotation; _startingUp = _up; } MovingVessel.SetWorldVelocity(Vector3d.zero); MovingVessel.angularVelocity = Vector3.zero; MovingVessel.angularMomentum = Vector3.zero; }
protected bool CheckUnderwater() { return(FlightGlobals.getAltitudeAtPos(intakeTransform.position) < 0.0f && vessel.mainBody.ocean); }
public double AtmosphericPressure() { return(FlightGlobals.getStaticPressure(vesselState.CoM)); }
public void FixedUpdate() { if (IsActivate == true) { //Landing Burn if (burn != null) { if (alreadyFired == false) { if (BurnRay()) { alreadyFired = true; } } else { if (this.vessel.situation != Vessel.Situations.LANDED || this.vessel.situation != Vessel.Situations.SPLASHED && burn.triggered) { foreach (Part p in this.vessel.parts) { if ((p.physicalSignificance == Part.PhysicalSignificance.FULL) && (p.rb != null)) { Vector3 gee = FlightGlobals.getGeeForceAtPosition(this.vessel.transform.position); p.AddForce(-gee.normalized * p.rb.mass * ((float)Math.Min(Math.Abs(this.vessel.verticalSpeed), gee.magnitude) + gee.magnitude)); } } Debug.Log(this.vessel.srf_velocity.magnitude); } } } //Inflate Buoy if (buoy != null) { if (alreadyInflated == false) { if (vessel.Splashed) { buoy.Inflate(); alreadyInflated = true; } } } //Airbag if (airbag != null) { //Inflate Airbag if (alreadyInflatedAirBag == false) { if (vessel.radarAltitude <= airbag.inflateAltitude) { airbag.Inflate(); alreadyInflatedAirBag = true; } } //Deflate Airbag if (alreadyInflatedAirBag == true && alreadyDeflatedAirBag == false) { if (vessel.Landed) { //Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>Landed!"); airbag.Deflate(); alreadyDeflatedAirBag = true; } else if (vessel.Splashed && airbag.damageAfterSplashed == true) { //Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>Splashed with damage"); airbag.Deflate(); alreadyDeflatedAirBag = true; } else if (vessel.Splashed && airbag.damageAfterSplashed == false) { //Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>Splashed with out damage"); airbag.Touchdown(); alreadyDeflatedAirBag = true; } } } //Check if (vessel.Landed || vessel.Splashed) { Events["Deactivate"].guiActive = false; Events["Activate"].guiActive = false; IsActivate = false; Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>The vessel has landed or splashed, deactivate pre-landing mode."); } } }
public void FixedUpdate() // FixedUpdate is also called when not activated { try { UpdateWasteheatBuffer(); if (!HighLogic.LoadedSceneIsFlight) { return; } if (!active) { base.OnFixedUpdate(); } effectiveRadiatorArea = EffectiveRadiatorArea; var external_temperature = FlightGlobals.getExternalTemperature(part.transform.position); wasteheatManager = getManagerForVessel(ResourceManager.FNRESOURCE_WASTEHEAT); // get resource bar ratio at start of frame wasteheatRatio = wasteheatManager.ResourceBarRatioBegin; if (Double.IsNaN(wasteheatRatio)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in wasteheatRatio"); return; } var normalized_atmosphere = Math.Min(vessel.atmDensity, 1); maxCurrentTemperature = maxAtmosphereTemperature * Math.Max(normalized_atmosphere, 0) + maxVacuumTemperature * Math.Max(Math.Min(1 - vessel.atmDensity, 1), 0); radiator_temperature_temp_val = external_temperature + Math.Min((maxRadiatorTemperature - external_temperature) * Math.Sqrt(wasteheatRatio), maxCurrentTemperature - external_temperature); var efficiency = 1 - Math.Pow(1 - wasteheatRatio, 400); var delta_temp = Math.Max(radiator_temperature_temp_val - Math.Max(external_temperature * normalized_atmosphere, 2.7), 0); if (radiatorIsEnabled) { if (!CheatOptions.IgnoreMaxTemperature && wasteheatRatio >= 1 && CurrentRadiatorTemperature >= maxRadiatorTemperature) { explode_counter++; if (explode_counter > 25) { part.explode(); } } else { explode_counter = 0; } var thermal_power_dissip_per_second = efficiency * Math.Pow(delta_temp, 4) * GameConstants.stefan_const * effectiveRadiatorArea / 1e6; if (Double.IsNaN(thermal_power_dissip_per_second)) { Debug.LogWarning("FNRadiator: FixedUpdate Single.IsNaN detected in fixed_thermal_power_dissip"); } radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermal_power_dissip_per_second) : 0; if (Double.IsNaN(radiatedThermalPower)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in radiatedThermalPower after call consumeWasteHeat (" + thermal_power_dissip_per_second + ")"); } instantaneous_rad_temp = Math.Max(radiator_temperature_temp_val, Math.Max(FlightGlobals.getExternalTemperature(vessel.altitude, vessel.mainBody), 2.7)); if (Double.IsNaN(instantaneous_rad_temp)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in instantaneous_rad_temp after reading external temperature"); } CurrentRadiatorTemperature = instantaneous_rad_temp; if (_moduleDeployableRadiator) { _moduleDeployableRadiator.hasPivot = pivotEnabled; } } else { double thermal_power_dissip_per_second = efficiency * Math.Pow(Math.Max(delta_temp - external_temperature, 0), 4) * GameConstants.stefan_const * effectiveRadiatorArea / 0.5e7; radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermal_power_dissip_per_second) : 0; instantaneous_rad_temp = Math.Max(radiator_temperature_temp_val, Math.Max(FlightGlobals.getExternalTemperature(vessel.altitude, vessel.mainBody), 2.7)); CurrentRadiatorTemperature = instantaneous_rad_temp; } if (vessel.atmDensity > 0) { var pressure = vessel.atmDensity; dynamic_pressure = 0.60205 * pressure * vessel.srf_velocity.sqrMagnitude / 101325; pressure += dynamic_pressure; var splashBonus = Math.Max(part.submergedPortion * 10, 1); var convection_delta_temp = Math.Max(0, CurrentRadiatorTemperature - external_temperature); var conv_power_dissip = efficiency * pressure * convection_delta_temp * effectiveRadiatorArea * 0.001 * convectiveBonus * splashBonus; if (!radiatorIsEnabled) { conv_power_dissip = conv_power_dissip / 2; } convectedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(conv_power_dissip) : 0; if (update_count == 6) { DeployMentControl(dynamic_pressure); } } else { convectedThermalPower = 0; if (!radiatorIsEnabled && isAutomated && canRadiateHeat && showControls && update_count == 6) { Debug.Log("[KSPI] - FixedUpdate Automated Deplotment "); Deploy(); } } } catch (Exception e) { Debug.LogError("[KSPI] - FNRadiator.FixedUpdate" + e.Message); } }
public override void Drive(FlightCtrlState s) // TODO put the brake in when running out of power to prevent nighttime solar failures on hills, or atleast try to { // TODO make distance calculation for 'reached' determination consider the rover and waypoint on sealevel to prevent height differences from messing it up -- should be done now? if (orbit.referenceBody != lastBody) { WaypointIndex = -1; Waypoints.Clear(); } MechJebWaypoint wp = (WaypointIndex > -1 && WaypointIndex < Waypoints.Count ? Waypoints[WaypointIndex] : null); var brake = vessel.ActionGroups[KSPActionGroup.Brakes]; // keep brakes locked if they are curSpeed = Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward); CalculateTraction(); speedIntAcc = speedPID.intAccum; if (wp != null && wp.Body == orbit.referenceBody) { if (ControlHeading) { heading.val = Math.Round(HeadingToPos(vessel.CoM, wp.Position), 1); } if (ControlSpeed) { var nextWP = (WaypointIndex < Waypoints.Count - 1 ? Waypoints[WaypointIndex + 1] : (LoopWaypoints ? Waypoints[0] : null)); var distance = Vector3.Distance(vessel.CoM, wp.Position); if (wp.Target != null) { distance += (float)(wp.Target.srfSpeed * curSpeed) / 2; } // var maxSpeed = (wp.MaxSpeed > 0 ? Math.Min((float)speed, wp.MaxSpeed) : speed); // use waypoints maxSpeed if set and smaller than set the speed or just stick with the set speed var maxSpeed = (wp.MaxSpeed > 0 ? wp.MaxSpeed : speed); // speed used to go towards the waypoint, using the waypoints maxSpeed if set or just stick with the set speed var minSpeed = (wp.MinSpeed > 0 ? wp.MinSpeed : (nextWP != null ? TurningSpeed((nextWP.MaxSpeed > 0 ? nextWP.MaxSpeed : speed), heading - HeadingToPos(wp.Position, nextWP.Position)) : (distance - wp.Radius > 50 ? turnSpeed.val : 1))); minSpeed = (wp.Quicksave ? 1 : minSpeed); // ^ speed used to go through the waypoint, using half the set speed or maxSpeed as minSpeed for routing waypoints (all except the last) var newSpeed = Math.Min(maxSpeed, Math.Max((distance - wp.Radius) / curSpeed, minSpeed)); // brake when getting closer newSpeed = (newSpeed > turnSpeed ? TurningSpeed(newSpeed, headingErr) : newSpeed); // reduce speed when turning a lot // if (LimitAcceleration) { newSpeed = curSpeed + Mathf.Clamp((float)(newSpeed - curSpeed), -1.5f, 0.5f); } // newSpeed = tgtSpeed + Mathf.Clamp((float)(newSpeed - tgtSpeed), -Time.deltaTime * 8f, Time.deltaTime * 2f); var radius = Math.Max(wp.Radius, 10); if (distance < radius) { if (WaypointIndex + 1 >= Waypoints.Count) // last waypoint { newSpeed = new [] { newSpeed, (distance < radius * 0.8 ? 0 : 1) }.Min(); // ^ limit speed so it'll only go from 1m/s to full stop when braking to prevent accidents on moons if (LoopWaypoints) { WaypointIndex = 0; } else { newSpeed = 0; brake = true; // tgtSpeed.force(newSpeed); if (curSpeed < brakeSpeedLimit) { if (wp.Quicksave) { //if (s.mainThrottle > 0) { s.mainThrottle = 0; } if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR) { WaypointIndex = -1; ControlHeading = ControlSpeed = false; QuickSaveLoad.QuickSave(); } } else { WaypointIndex = -1; ControlHeading = ControlSpeed = false; } } // else { // Debug.Log("Is this even getting called?"); // WaypointIndex++; // } } } else { if (wp.Quicksave) { //if (s.mainThrottle > 0) { s.mainThrottle = 0; } newSpeed = 0; // tgtSpeed.force(newSpeed); if (curSpeed < brakeSpeedLimit) { if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR) { WaypointIndex++; QuickSaveLoad.QuickSave(); } } } else { WaypointIndex++; } } } brake = brake || ((s.wheelThrottle == 0 || !vessel.isActiveVessel) && curSpeed < brakeSpeedLimit && newSpeed < brakeSpeedLimit); // ^ brake if needed to prevent rolling, hopefully tgtSpeed = (newSpeed >= 0 ? newSpeed : 0); } } if (ControlHeading) { headingPID.intAccum = Mathf.Clamp((float)headingPID.intAccum, -1, 1); double instantaneousHeading = vesselState.rotationVesselSurface.eulerAngles.y; headingErr = MuUtils.ClampDegrees180(instantaneousHeading - heading); if (s.wheelSteer == s.wheelSteerTrim || FlightGlobals.ActiveVessel != vessel) { float limit = (Math.Abs(curSpeed) > turnSpeed ? Mathf.Clamp((float)((turnSpeed + 6) / Square(curSpeed)), 0.1f, 1f) : 1f); // turnSpeed needs to be higher than curSpeed or it will never steer as much as it could even at 0.2m/s above it // double act = headingPID.Compute(headingErr * headingErr / 10 * Math.Sign(headingErr)); double act = headingPID.Compute(headingErr); if (traction >= tractionLimit) { s.wheelSteer = Mathf.Clamp((float)act, -limit, limit); // prevents it from flying above a waypoint and landing with steering at max while still going fast } } } // Brake if there is no controler (Pilot eject from seat) if (BrakeOnEject && vessel.GetReferenceTransformPart() == null) { s.wheelThrottle = 0; // vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); brake = true; } else if (ControlSpeed) { speedPID.intAccum = Mathf.Clamp((float)speedPID.intAccum, -5, 5); speedErr = (WaypointIndex == -1 ? speed.val : tgtSpeed) - Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward); if (s.wheelThrottle == s.wheelThrottleTrim || FlightGlobals.ActiveVessel != vessel) { float act = (float)speedPID.Compute(speedErr); s.wheelThrottle = Mathf.Clamp(act, -1f, 1f); // s.wheelThrottle = (!LimitAcceleration ? Mathf.Clamp(act, -1, 1) : // I think I'm using these ( ? : ) a bit too much // (traction == 0 ? 0 : (act < 0 ? Mathf.Clamp(act, -1f, 1f) : (lastThrottle + Mathf.Clamp(act - lastThrottle, -0.01f, 0.01f)) * (traction < tractionLimit ? -1 : 1)))); // (lastThrottle + Mathf.Clamp(act, -0.01f, 0.01f))); // Debug.Log(s.wheelThrottle + Mathf.Clamp(act, -0.01f, 0.01f)); if (curSpeed < 0 & s.wheelThrottle < 0) { s.wheelThrottle = 0; } // don't go backwards if (Mathf.Sign(act) + Mathf.Sign(s.wheelThrottle) == 0) { s.wheelThrottle = Mathf.Clamp(act, -1f, 1f); } if (speedErr < -1 && StabilityControl && Mathf.Sign(s.wheelThrottle) + Math.Sign(curSpeed) == 0) // StabilityControl && traction > 50 && //// vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); { brake = true; // foreach (Part p in wheels) { // if (p.GetModule<ModuleWheels.ModuleWheelDamage>().stressPercent >= 0.01) { // #TODO needs adaptive braking // brake = false; // break; // } // } } //// else if (!StabilityControl || traction <= 50 || speedErr > -0.2 || Mathf.Sign(s.wheelThrottle) + Mathf.Sign((float)curSpeed) != 0) { //// vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, (GameSettings.BRAKES.GetKey() && vessel.isActiveVessel)); //// } lastThrottle = Mathf.Clamp(s.wheelThrottle, -1, 1); } } if (StabilityControl) { if (!core.attitude.users.Contains(this)) { core.attitude.users.Add(this); // line.enabled = true; } // float scale = Vector3.Distance(FlightCamera.fetch.mainCamera.transform.position, vessel.CoM) / 900f; // line.SetPosition(0, vessel.CoM); // line.SetPosition(1, vessel.CoM + hit.normal * 5); // line.SetWidth(0, scale + 0.1f); var fSpeed = (float)curSpeed; // if (Mathf.Abs(fSpeed) >= turnSpeed * 0.75) { Vector3 fwd = (Vector3)(traction > 0 ? // V when the speed is low go for the vessels forward, else with a bit of velocity // ((Mathf.Abs(fSpeed) <= turnSpeed ? vesselState.forward : vesselState.surfaceVelocity / 4) - vessel.transform.right * s.wheelSteer) * Mathf.Sign(fSpeed) : // // ^ and then add the steering vesselState.forward * 4 - vessel.transform.right * s.wheelSteer * Mathf.Sign(fSpeed) : // and then add the steering vesselState.surfaceVelocity); // in the air so follow velocity Vector3.OrthoNormalize(ref norm, ref fwd); var quat = Quaternion.LookRotation(fwd, norm); // if (traction > 0 || speed <= turnSpeed) { // var u = new Vector3(0, 1, 0); // // var q = FlightGlobals.ship_rotation; // var q_s = quat; // // var q_u = new Quaternion(u.x, u.y, u.z, 0); // var a = Quaternion.Dot(q, q_s * q_u); // var q_qs = Quaternion.Dot(q, q_s); // var b = (a == 0) ? Math.Sign(q_qs) : (q_qs / a); // var g = b / Mathf.Sqrt((b * b) + 1); // var gu = Mathf.Sqrt(1 - (g * g)) * u; // var q_d = new Quaternion() { w = g, x = gu.x, y = gu.y, z = gu.z }; // var n = q_s * q_d; // // quat = n; // } if (vesselState.torqueAvailable.sqrMagnitude > 0) { core.attitude.attitudeTo(quat, AttitudeReference.INERTIAL, this); } // } } if (BrakeOnEnergyDepletion) { var batteries = vessel.Parts.FindAll(p => p.Resources.Contains(PartResourceLibrary.ElectricityHashcode) && p.Resources.Get(PartResourceLibrary.ElectricityHashcode).flowState); var energyLeft = batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).amount) / batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).maxAmount); var openSolars = vessel.mainBody.atmosphere && // true if in atmosphere and there are breakable solarpanels that aren't broken nor retracted vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable && p.deployState != ModuleDeployablePart.DeployState.BROKEN && p.deployState != ModuleDeployablePart.DeployState.RETRACTED).Count > 0; if (openSolars && energyLeft > 0.99) { vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable && p.deployState == ModuleDeployablePart.DeployState.EXTENDED).ForEach(p => p.Retract()); } if (energyLeft < 0.05 && Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0) { s.wheelThrottle = 0; } // save remaining energy by not using it for acceleration if (openSolars || energyLeft < 0.03) { tgtSpeed = 0; } if (curSpeed < brakeSpeedLimit && (energyLeft < 0.05 || openSolars)) { brake = true; } if (curSpeed < 0.1 && energyLeft < 0.05 && !waitingForDaylight && vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.deployState == ModuleDeployablePart.DeployState.EXTENDED).Count > 0) { waitingForDaylight = true; } } // brake = brake && (s.wheelThrottle == 0); // release brake if the user or AP want to drive if (s.wheelThrottle != 0 && (Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0 || curSpeed < 1)) { brake = false; // the AP or user want to drive into the direction of momentum so release the brake } if (vessel.isActiveVessel) { if (GameSettings.BRAKES.GetKeyUp()) { brake = false; // release the brakes if the user lets go of them } if (GameSettings.BRAKES.GetKey()) { brake = true; // brake if the user brakes and we aren't about to flip } } tractionLimit = (double)Mathf.Clamp((float)tractionLimit, 0, 100); vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, brake && (StabilityControl && (ControlHeading || ControlSpeed) ? traction >= tractionLimit : true)); // only let go of the brake when losing traction if the AP is driving, otherwise assume the player knows when to let go of it // also to not constantly turn off the parking brake from going over a small bump if (brake && curSpeed < 0.1) { s.wheelThrottle = 0; } }
public static Vector3d computeTotalAccel(Vector3d pos, Vector3d orbitVel, double dragCoeffOverMass, CelestialBody body) { return(FlightGlobals.getGeeForceAtPosition(pos) + computeDragAccel(pos, orbitVel, dragCoeffOverMass, body)); }
public void FixedUpdate() { if (initializationCountdown > 0) { initializationCountdown--; } if (!HighLogic.LoadedSceneIsFlight) { return; } if (_attached_engine == null) { return; } if (_attached_engine is ModuleEnginesFX) { ElectricEngineControllerFX.getAllPropellants().ForEach(prop => part.Effect(prop.ParticleFXName, 0, -1)); // set all FX to zero } if (Current_propellant == null) { return; } if (!this.vessel.packed && !warpToReal) { storedThrotle = vessel.ctrlState.mainThrottle; } // retrieve power maxEffectivePower = MaxEffectivePower; var sumOfAllEffectivePower = vessel.FindPartModulesImplementing <ElectricEngineControllerFX>().Where(ee => ee.IsOperational).Sum(ee => ee.MaxEffectivePower); _electrical_share_f = sumOfAllEffectivePower > 0 ? maxEffectivePower / sumOfAllEffectivePower : 1; maxThrottlePower = maxEffectivePower * ModifiedThrotte; var currentPropellantEfficiency = CurrentPropellantEfficiency; if (CheatOptions.InfiniteElectricity) { power_request = maxThrottlePower; } else { var availablePower = Math.Max(getStableResourceSupply(FNResourceManager.FNRESOURCE_MEGAJOULES) - getCurrentHighPriorityResourceDemand(FNResourceManager.FNRESOURCE_MEGAJOULES), 0); var megaJoulesBarRatio = getResourceBarRatio(FNResourceManager.FNRESOURCE_MEGAJOULES); var effectiveResourceThrotling = megaJoulesBarRatio > oneThird ? 1 : megaJoulesBarRatio * 3; var power_per_engine = effectiveResourceThrotling * ModifiedThrotte * EvaluateMaxThrust(availablePower * _electrical_share_f) * CurrentIspMultiplier * _modifiedEngineBaseISP / GetPowerThrustModifier() * _g0; power_request = currentPropellantEfficiency <= 0 ? 0 : Math.Min(power_per_engine / currentPropellantEfficiency, maxThrottlePower); } var power_received = CheatOptions.InfiniteElectricity ? power_request : consumeFNResource(power_request * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime; // produce waste heat var heat_to_produce = power_received * (1 - currentPropellantEfficiency) * Current_propellant.WasteHeatMultiplier; var heat_production = CheatOptions.IgnoreMaxTemperature ? heat_to_produce : supplyFNResourceFixed(heat_to_produce * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime; // update GUI Values _electrical_consumption_f = power_received; _heat_production_f = heat_production; var effectiveIsp = _modifiedCurrentPropellantIspMultiplier * _modifiedEngineBaseISP * ThrottleModifiedIsp(); var max_thrust_in_space = currentPropellantEfficiency * CurrentPropellantThrustMultiplier * ModifiedThrotte * GetPowerThrustModifier() * power_received / (effectiveIsp * _g0); _maxISP = _modifiedEngineBaseISP * _modifiedCurrentPropellantIspMultiplier * CurrentPropellantThrustMultiplier * ThrottleModifiedIsp(); _max_fuel_flow_rate = _maxISP <= 0 ? 0 : max_thrust_in_space / _maxISP / PluginHelper.GravityConstant; var max_thrust_with_current_throttle = max_thrust_in_space * ModifiedThrotte; throtle_max_thrust = Current_propellant.SupportedEngines == 8 ? max_thrust_with_current_throttle : Math.Max(max_thrust_with_current_throttle - (exitArea * FlightGlobals.getStaticPressure(vessel.transform.position)), 0); float throttle = _attached_engine.currentThrottle > 0 ? Mathf.Max(_attached_engine.currentThrottle, 0.01f) : 0; //if (ModifiedThrotte > 0) if (throttle > 0 && !this.vessel.packed) { if (IsValidPositiveNumber(throtle_max_thrust) && IsValidPositiveNumber(max_thrust_with_current_throttle)) { updateISP(throtle_max_thrust / max_thrust_with_current_throttle); _attached_engine.maxFuelFlow = (float)Math.Max(_max_fuel_flow_rate * (ModifiedThrotte / _attached_engine.currentThrottle), 0.0000000001); } else { updateISP(0.000001); _attached_engine.maxFuelFlow = 0.0000000001f; } if (_attached_engine is ModuleEnginesFX) { this.part.Effect(Current_propellant.ParticleFXName, Mathf.Min((float)Math.Pow(_electrical_consumption_f / maxEffectivePower, 0.5), _attached_engine.finalThrust / _attached_engine.maxThrust), -1); } } else if (this.vessel.packed && _attached_engine.enabled && FlightGlobals.ActiveVessel == vessel && throttle > 0 && initializationCountdown == 0) { warpToReal = true; // Set to true for transition to realtime PersistantThrust(TimeWarp.fixedDeltaTime, Planetarium.GetUniversalTime(), this.part.transform.up, this.vessel.GetTotalMass()); } else { throtle_max_thrust = 0; var projected_max_thrust = Math.Max(max_thrust_in_space - (exitArea * FlightGlobals.getStaticPressure(vessel.transform.position)), 0); if (IsValidPositiveNumber(projected_max_thrust) && IsValidPositiveNumber(max_thrust_in_space)) { updateISP(projected_max_thrust / max_thrust_in_space); _attached_engine.maxFuelFlow = (float)Math.Max(_max_fuel_flow_rate, 0.0000000001); } else { updateISP(1); _attached_engine.maxFuelFlow = 0.0000000001f; } if (_attached_engine is ModuleEnginesFX) { this.part.Effect(Current_propellant.ParticleFXName, 0, -1); } } if (isupgraded && vacuumPlasmaResource != null) { //vacuumPlasmaResource.maxAmount = maxPower * 0.00001 * TimeWarp.fixedDeltaTime; this.part.RequestResource(InterstellarResourcesConfiguration.Instance.VacuumPlasma, -vacuumPlasmaResource.maxAmount); } }
internal void BuildAndLaunchCraft() { // build craft ShipConstruct nship = new ShipConstruct(); nship.LoadShip(craftConfig); string landedAt = ""; string flag = flagname; Game game = FlightDriver.FlightStateCache; VesselCrewManifest crew = new VesselCrewManifest(); Box vessel_bounds = GetVesselBox(nship); launchTransform = builder.PlaceShip(nship, vessel_bounds); EnableExtendingLaunchClamps(nship); ShipConstruction.AssembleForLaunch(nship, landedAt, landedAt, flag, game, crew); var FlightVessels = FlightGlobals.Vessels; craftVessel = FlightVessels[FlightVessels.Count - 1]; craftVessel.launchedFrom = builder.LaunchedFrom; FlightGlobals.ForceSetActiveVessel(craftVessel); if (builder.capture) { craftVessel.Splashed = craftVessel.Landed = false; } else { bool loaded = craftVessel.loaded; bool packed = craftVessel.packed; craftVessel.loaded = true; craftVessel.packed = false; // The default situation for new vessels is PRELAUNCH, but // that is not so good for bases because contracts check for // LANDED. XXX should this be selectable? craftVessel.situation = Vessel.Situations.LANDED; craftVessel.GetHeightFromTerrain(); Debug.Log($"[ELBuildControl] height from terrain {craftVessel.heightFromTerrain}"); craftVessel.loaded = loaded; craftVessel.packed = packed; } Vector3 offset = craftVessel.transform.position - launchTransform.position; craftOffset = launchTransform.InverseTransformDirection(offset); SetupCraftResources(craftVessel); KSP.UI.Screens.StageManager.BeginFlight(); builtStuff = null; // ensure pad mass gets reset SetPadMass(); if (builder.capture) { FlightGlobals.overrideOrbit = true; (builder as PartModule).StartCoroutine(CaptureCraft()); } else { CleaupAfterRelease(); } }
public override void Drive(FlightCtrlState s) // TODO put the brake in when running out of power to prevent nighttime solar failures on hills, or atleast try to { // TODO make distance calculation for 'reached' determination consider the rover and waypoint on sealevel to prevent height differences from messing it up if (orbit.referenceBody != lastBody) { WaypointIndex = -1; Waypoints.Clear(); } MechJebRoverWaypoint wp = (WaypointIndex > -1 && WaypointIndex < Waypoints.Count ? Waypoints[WaypointIndex] : null); var curSpeed = vesselState.speedSurface; etaSpeed.value = curSpeed; if (wp != null && wp.Body == orbit.referenceBody) { if (controlHeading) { heading = Math.Round(HeadingToPos(vessel.CoM, wp.Position), 1); } if (controlSpeed) { var nextWP = (WaypointIndex < Waypoints.Count - 1 ? Waypoints[WaypointIndex + 1] : (LoopWaypoints ? Waypoints[0] : null)); var distance = Vector3.Distance(vessel.CoM, wp.Position); //var maxSpeed = (wp.MaxSpeed > 0 ? Math.Min((float)speed, wp.MaxSpeed) : speed); // use waypoints maxSpeed if set and smaller than set the speed or just stick with the set speed var maxSpeed = (wp.MaxSpeed > 0 ? wp.MaxSpeed : speed); // speed used to go towards the waypoint, using the waypoints maxSpeed if set or just stick with the set speed var minSpeed = (wp.MinSpeed > 0 ? wp.MinSpeed : (nextWP != null ? TurningSpeed((nextWP.MaxSpeed > 0 ? nextWP.MaxSpeed : speed), heading - HeadingToPos(wp.Position, nextWP.Position)) : (distance - wp.Radius > 50 ? turnSpeed.val : 1))); minSpeed = (wp.Quicksave ? 0 : minSpeed); // ^ speed used to go through the waypoint, using half the set speed or maxSpeed as minSpeed for routing waypoints (all except the last) var brakeFactor = Math.Max((curSpeed - minSpeed) * 1, 3); var newSpeed = Math.Min(maxSpeed, Math.Max((distance - wp.Radius) / brakeFactor, minSpeed)); // brake when getting closer newSpeed = (newSpeed > turnSpeed ? TurningSpeed(newSpeed, headingErr) : newSpeed); // reduce speed when turning a lot var radius = Math.Max(wp.Radius, 10 / 0.8); // alternative radius so negative radii can still make it go full speed through waypoints for navigation reasons if (distance < radius) { if (WaypointIndex + 1 >= Waypoints.Count) // last waypoint { newSpeed = new [] { newSpeed, (distance < radius * 0.8 ? 0 : 1) }.Min(); // ^ limit speed so it'll only go from 1m/s to full stop when braking to prevent accidents on moons if (LoopWaypoints) { WaypointIndex = 0; } else { newSpeed = -0.25; tgtSpeed.force(newSpeed); if (curSpeed < 0.85) { if (wp.Quicksave) { if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR) { WaypointIndex = -1; controlHeading = controlSpeed = false; QuickSaveLoad.QuickSave(); } } else { WaypointIndex = -1; controlHeading = controlSpeed = false; } } // else { // Debug.Log("Is this even getting called?"); // WaypointIndex++; // } } } else { if (wp.Quicksave) { newSpeed = -0.25; tgtSpeed.force(newSpeed); if (curSpeed < 0.85) { if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR) { WaypointIndex++; QuickSaveLoad.QuickSave(); } } } else { WaypointIndex++; } } } vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, (GameSettings.BRAKES.GetKey() && vessel.isActiveVessel) || ((s.wheelThrottle == 0 || !vessel.isActiveVessel) && curSpeed < 0.85 && newSpeed < 0.85)); // ^ brake if needed to prevent rolling, hopefully tgtSpeed.value = Math.Round(newSpeed, 1); } } if (controlHeading) { if (heading != headingLast) { headingPID.Reset(); headingLast = heading; } double instantaneousHeading = vesselState.rotationVesselSurface.eulerAngles.y; headingErr = MuUtils.ClampDegrees180(instantaneousHeading - heading); if (s.wheelSteer == s.wheelSteerTrim || FlightGlobals.ActiveVessel != vessel) { float spd = Mathf.Min((float)speed, (float)turnSpeed); // if a slower speed than the turnspeed is used also be more careful with the steering float limit = (curSpeed <= turnSpeed ? 1 : Mathf.Clamp((float)((spd * spd) / (curSpeed * curSpeed)), 0.2f, 1f)); double act = headingPID.Compute(headingErr); s.wheelSteer = Mathf.Clamp((float)act, -limit, limit); } } // Brake if there is no controler (Pilot eject from seat) if (brakeOnEject && vessel.GetReferenceTransformPart() == null) { s.wheelThrottle = 0; vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true); } else if (controlSpeed) { if (speed != speedLast) { speedPID.Reset(); speedLast = speed; } speedErr = (WaypointIndex == -1 ? speed.val : tgtSpeed.value) - Vector3d.Dot(vesselState.velocityVesselSurface, vesselState.forward); if (s.wheelThrottle == s.wheelThrottleTrim || FlightGlobals.ActiveVessel != vessel) { double act = speedPID.Compute(speedErr); s.wheelThrottle = Mathf.Clamp((float)act, -1, 1); } } }
public override void Drive(FlightCtrlState s) // TODO put the brake in when running out of power to prevent nighttime solar failures on hills, or atleast try to { // TODO make distance calculation for 'reached' determination consider the rover and waypoint on sealevel to prevent height differences from messing it up -- should be done now? if (orbit.referenceBody != lastBody) { WaypointIndex = -1; Waypoints.Clear(); } MechJebWaypoint wp = (WaypointIndex > -1 && WaypointIndex < Waypoints.Count ? Waypoints[WaypointIndex] : null); bool brake = vessel.ActionGroups[KSPActionGroup.Brakes]; // keep brakes locked if they are curSpeed = Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward); CalculateTraction(); speedIntAcc = speedPID.intAccum; if (wp != null && wp.Body == orbit.referenceBody) { if (ControlHeading) { double newHeading = Math.Round(HeadingToPos(vessel.CoM, wp.Position), 1); // update GUI text only if the value changed if (newHeading != heading) { heading.val = newHeading; } } if (ControlSpeed) { MechJebWaypoint nextWP = (WaypointIndex < Waypoints.Count - 1 ? Waypoints[WaypointIndex + 1] : (LoopWaypoints ? Waypoints[0] : null)); float distance = Vector3.Distance(vessel.CoM, wp.Position); if (wp.Target != null) { distance += (float)(wp.Target.srfSpeed * curSpeed) / 2; } // var maxSpeed = (wp.MaxSpeed > 0 ? Math.Min((float)speed, wp.MaxSpeed) : speed); // use waypoints maxSpeed if set and smaller than set the speed or just stick with the set speed double maxSpeed = (wp.MaxSpeed > 0 ? wp.MaxSpeed : speed); // speed used to go towards the waypoint, using the waypoints maxSpeed if set or just stick with the set speed double minSpeed = (wp.MinSpeed > 0 ? wp.MinSpeed : (nextWP != null ? TurningSpeed((nextWP.MaxSpeed > 0 ? nextWP.MaxSpeed : speed), MuUtils.ClampDegrees180(heading - HeadingToPos(wp.Position, nextWP.Position))) : (distance - wp.Radius > 50 ? turnSpeed.val : 1))); minSpeed = (wp.Quicksave ? 1 : minSpeed); // ^ speed used to go through the waypoint, using half the set speed or maxSpeed as minSpeed for routing waypoints (all except the last) double newSpeed = Math.Min(maxSpeed, Math.Max((distance - wp.Radius) / curSpeed, minSpeed)); // brake when getting closer newSpeed = (newSpeed > turnSpeed ? TurningSpeed(newSpeed, headingErr) : newSpeed); // reduce speed when turning a lot float radius = Math.Max(wp.Radius, 10); if (distance < radius) { if (WaypointIndex + 1 >= Waypoints.Count) // last waypoint { newSpeed = new [] { newSpeed, (distance < radius * 0.8 ? 0 : 1) }.Min(); // ^ limit speed so it'll only go from 1m/s to full stop when braking to prevent accidents on moons if (LoopWaypoints) { WaypointIndex = 0; } else { newSpeed = 0; brake = true; if (curSpeed < brakeSpeedLimit) { if (wp.Quicksave) { if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR) { WaypointIndex = -1; ControlHeading = ControlSpeed = false; QuickSaveLoad.QuickSave(); } } else { WaypointIndex = -1; ControlHeading = ControlSpeed = false; } } } } else { if (wp.Quicksave) { newSpeed = 0; if (curSpeed < brakeSpeedLimit) { if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR) { WaypointIndex++; QuickSaveLoad.QuickSave(); } } } else { WaypointIndex++; } } } brake = brake || ((s.wheelThrottle == 0 || !vessel.isActiveVessel) && curSpeed < brakeSpeedLimit && newSpeed < brakeSpeedLimit); // ^ brake if needed to prevent rolling, hopefully tgtSpeed = (newSpeed >= 0 ? newSpeed : 0); } } if (ControlHeading) { headingPID.intAccum = Mathf.Clamp((float)headingPID.intAccum, -1, 1); double instantaneousHeading = vesselState.rotationVesselSurface.eulerAngles.y; headingErr = MuUtils.ClampDegrees180(instantaneousHeading - heading); if (s.wheelSteer == s.wheelSteerTrim || FlightGlobals.ActiveVessel != vessel) { float limit = (Math.Abs(curSpeed) > turnSpeed ? Mathf.Clamp((float)((turnSpeed + 6) / Square(curSpeed)), 0.1f, 1f) : 1f); // turnSpeed needs to be higher than curSpeed or it will never steer as much as it could even at 0.2m/s above it double act = headingPID.Compute(headingErr); if (traction >= tractionLimit) { s.wheelSteer = Mathf.Clamp((float)act, -limit, limit); // prevents it from flying above a waypoint and landing with steering at max while still going fast } } } // Brake if there is no controler (Pilot eject from seat) if (BrakeOnEject && vessel.GetReferenceTransformPart() == null) { s.wheelThrottle = 0; brake = true; } else if (ControlSpeed) { speedPID.intAccum = Mathf.Clamp((float)speedPID.intAccum, -5, 5); speedErr = (WaypointIndex == -1 ? speed.val : tgtSpeed) - Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward); if (s.wheelThrottle == s.wheelThrottleTrim || FlightGlobals.ActiveVessel != vessel) { float act = (float)speedPID.Compute(speedErr); s.wheelThrottle = Mathf.Clamp(act, -1f, 1f); if (curSpeed < 0 & s.wheelThrottle < 0) { s.wheelThrottle = 0; } // don't go backwards if (Mathf.Sign(act) + Mathf.Sign(s.wheelThrottle) == 0) { s.wheelThrottle = Mathf.Clamp(act, -1f, 1f); } if (speedErr < -1 && StabilityControl && Mathf.Sign(s.wheelThrottle) + Math.Sign(curSpeed) == 0) { brake = true; } lastThrottle = Mathf.Clamp(s.wheelThrottle, -1, 1); } } if (StabilityControl) { RaycastHit hit; Physics.Raycast(vessel.CoM + vesselState.surfaceVelocity * terrainLookAhead + vesselState.up * 100, -vesselState.up, out hit, 500, 1 << 15, QueryTriggerInteraction.Ignore); Vector3 norm = hit.normal; if (!core.attitude.users.Contains(this)) { core.attitude.users.Add(this); } float fSpeed = (float)curSpeed; Vector3 fwd = (Vector3)(traction > 0 ? // V when the speed is low go for the vessels forward, else with a bit of velocity vesselState.forward * 4 - vessel.transform.right * s.wheelSteer * Mathf.Sign(fSpeed) : // and then add the steering vesselState.surfaceVelocity); // in the air so follow velocity Vector3.OrthoNormalize(ref norm, ref fwd); Quaternion quat = Quaternion.LookRotation(fwd, norm); if (vesselState.torqueAvailable.sqrMagnitude > 0) { core.attitude.attitudeTo(quat, AttitudeReference.INERTIAL, this); } } if (BrakeOnEnergyDepletion) { var batteries = vessel.Parts.FindAll(p => p.Resources.Contains(PartResourceLibrary.ElectricityHashcode) && p.Resources.Get(PartResourceLibrary.ElectricityHashcode).flowState); var energyLeft = batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).amount) / batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).maxAmount); var openSolars = vessel.mainBody.atmosphere && // true if in atmosphere and there are breakable solarpanels that aren't broken nor retracted vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable && p.deployState != ModuleDeployablePart.DeployState.BROKEN && p.deployState != ModuleDeployablePart.DeployState.RETRACTED).Count > 0; if (openSolars && energyLeft > 0.99) { vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable && p.deployState == ModuleDeployablePart.DeployState.EXTENDED).ForEach(p => p.Retract()); } if (energyLeft < 0.05 && Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0) { s.wheelThrottle = 0; } // save remaining energy by not using it for acceleration if (openSolars || energyLeft < 0.03) { tgtSpeed = 0; } if (curSpeed < brakeSpeedLimit && (energyLeft < 0.05 || openSolars)) { brake = true; } if (curSpeed < 0.1 && energyLeft < 0.05 && !waitingForDaylight && vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.deployState == ModuleDeployablePart.DeployState.EXTENDED).Count > 0) { waitingForDaylight = true; } } if (s.wheelThrottle != 0 && (Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0 || curSpeed < 1)) { brake = false; // the AP or user want to drive into the direction of momentum so release the brake } if (vessel.isActiveVessel) { if (GameSettings.BRAKES.GetKeyUp()) { brake = false; // release the brakes if the user lets go of them } if (GameSettings.BRAKES.GetKey()) { brake = true; // brake if the user brakes and we aren't about to flip } } tractionLimit = (double)Mathf.Clamp((float)tractionLimit, 0, 100); vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, brake && (StabilityControl && (ControlHeading || ControlSpeed) ? traction >= tractionLimit : true)); // only let go of the brake when losing traction if the AP is driving, otherwise assume the player knows when to let go of it // also to not constantly turn off the parking brake from going over a small bump if (brake && curSpeed < 0.1) { s.wheelThrottle = 0; } }
private void UpdateKolonizationStats() { //No kolonization on Kerbin! if (vessel.mainBody == FlightGlobals.GetHomeBody()) { return; } var k = KolonizationManager.Instance.FetchLogEntry(vessel.id.ToString(), vessel.mainBody.flightGlobalsIndex); if (Planetarium.GetUniversalTime() - k.LastUpdate < checkTime) { return; } var numPilots = GetVesselCrewByTrait("Pilot"); var numEngineers = GetVesselCrewByTrait("Engineer"); var numScientists = GetVesselCrewByTrait("Scientist"); var elapsedTime = Planetarium.GetUniversalTime() - k.LastUpdate; var orbitMod = 1d; if (!vessel.LandedOrSplashed) { orbitMod = KolonizationSetup.Instance.Config.OrbitMultiplier; } var scienceBase = numScientists * elapsedTime * orbitMod; var repBase = numPilots * elapsedTime * orbitMod; var fundsBase = numEngineers * elapsedTime * orbitMod; k.LastUpdate = Planetarium.GetUniversalTime(); k.BotanyResearch += scienceBase; k.KolonizationResearch += repBase; k.GeologyResearch += fundsBase; var mult = vessel.mainBody.scienceValues.RecoveryValue; var science = scienceBase * KolonizationSetup.Instance.Config.ScienceMultiplier * mult; var rep = repBase * KolonizationSetup.Instance.Config.RepMultiplier * mult; var funds = fundsBase * KolonizationSetup.Instance.Config.FundsMultiplier * mult; k.Science += science; k.Funds += funds; k.Rep += rep; KolonizationManager.Instance.TrackLogEntry(k); //Update the hab bonus var thisBodyInfo = KolonizationManager.Instance.KolonizationInfo.Where(b => b.BodyIndex == vessel.mainBody.flightGlobalsIndex); var habBonus = thisBodyInfo.Sum(b => b.KolonizationResearch); habBonus = Math.Sqrt(habBonus); habBonus /= KolonizationSetup.Instance.Config.EfficiencyMultiplier; USI_GlobalBonuses.Instance.SaveHabBonus(vessel.mainBody.flightGlobalsIndex, habBonus); //Update the drill bonus foreach (var d in vessel.FindPartModulesImplementing <BaseDrill>()) { var geoBonus = thisBodyInfo.Sum(b => b.GeologyResearch); geoBonus = Math.Sqrt(habBonus); geoBonus /= KolonizationSetup.Instance.Config.EfficiencyMultiplier; geoBonus += KolonizationSetup.Instance.Config.StartingBaseBonus; d.EfficiencyBonus = (float)Math.Max(KolonizationSetup.Instance.Config.MinBaseBonus, geoBonus); } }
void Update() { CastSpell(); if (loading) { //Debug.Log($"reset: {reset}, stage: {stage}, grav: {PhysicsGlobals.GraviticForceMultiplier}, pos: {FlightGlobals.currentMainBody.pqsController.target.position}"); if (!FlightGlobals.currentMainBody.pqsController.isBuildingMaps) { --reset; } if (reset <= 0) { reset = vesLoad; switch (stage) { case 0: vesEnume = FlightGlobals.VesselsLoaded.ToList().GetEnumerator(); tvel = FlightGlobals.ActiveVessel; ++stage; break; case 1: if (vesEnume.Current != null) { vesEnume.Current.OnFlyByWire -= thratlarasat; } if (vesEnume.MoveNext()) { if (sortaLanded(vesEnume.Current)) { FlightGlobals.ForceSetActiveVessel(vesEnume.Current); } vesEnume.Current.OnFlyByWire += thratlarasat; } else { vesEnume.Dispose(); ++stage; FlightGlobals.ForceSetActiveVessel(tvel); } Debug.LogError($"Black Spell entangling {vesEnume.Current?.vesselName}"); break; case 2: Debug.LogError("Black Spell condensing"); ++stage; break; case 3: Debug.LogError("Black Spell releasing energies"); reset = 100; ++stage; break; case 4: CheatOptions.NoCrashDamage = crashDamage; CheatOptions.UnbreakableJoints = joints; loading = false; Debug.LogError("Black Spell complete"); break; } } } }
public void FixedUpdate() { if (HighLogic.LoadedSceneIsEditor) { UpdateBalloonType(); } if (HighLogic.LoadedSceneIsFlight) { //print("hasInflated: " + hasInflated + " | isInflated: " + isInflated + " | isInflating: " + isInflating + " | isDeflating: " + isDeflating + " | hasBurst: " + hasBurst + " | isRepacked: " + isRepacked); float currentPressure = (float)FlightGlobals.getStaticPressure(this.part.transform.position); if (hasInflated && !hasBurst) { if (isInflated) { float lift = BalloonProperties.getLift(this); this.part.AddForceAtPosition(vessel.upAxis * lift, liftPointObject.transform.position); Vector3 scale = new Vector3(BalloonProperties.getScale(this), BalloonProperties.getScale(this), BalloonProperties.getScale(this)); balloonObject.transform.localScale = scale; ropeObject.transform.rotation = Quaternion.Slerp(ropeObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 10); balloonObject.transform.rotation = Quaternion.Slerp(balloonObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 8); balloonObject.transform.position = balloonPointObject.transform.position; if (currentPressure < minAtmoPressure || currentPressure > maxAtmoPressure) { hasBurst = true; } } else if (isDeflating) { if (scaleInc > 0) { scaleInc -= BalloonProperties.getScale(this) / 100; balloonObject.transform.localScale = new Vector3(scaleInc, scaleInc, scaleInc); float progress = scaleInc / BalloonProperties.getScale(this); float lift = BalloonProperties.getLift(this) * progress; this.part.AddForceAtPosition(vessel.upAxis * lift, liftPointObject.transform.position); ropeObject.transform.localScale = new Vector3(1, 1, progress); balloonObject.transform.position = balloonPointObject.transform.position; } else { balloonObject.SetActive(false); ropeObject.SetActive(false); isInflated = false; isDeflating = false; isRepacked = false; } } else if (!isInflated && !isInflating && !isDeflating && !isRepacked) { Events["repackBalloon"].active = true; } } else if (isInflating && !hasBurst) { if (scaleInc < BalloonProperties.getScale(this)) { scaleInc += BalloonProperties.getScale(this) / 200; balloonObject.transform.localScale = new Vector3(scaleInc, scaleInc, scaleInc); float progress = scaleInc / BalloonProperties.getScale(this); float lift = BalloonProperties.getLift(this) * progress; this.part.AddForceAtPosition(vessel.upAxis * lift, liftPointObject.transform.position); ropeObject.transform.rotation = Quaternion.Slerp(ropeObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 10); balloonObject.transform.rotation = Quaternion.Slerp(balloonObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 8); ropeObject.transform.localScale = new Vector3(1, 1, progress); balloonObject.transform.position = balloonPointObject.transform.position; } else { hasInflated = true; isInflated = true; isInflating = false; } } else if (hasBurst && (isInflated || isInflating || isDeflating)) { this.part.Effect("burst"); isInflated = false; isInflating = false; isDeflating = false; balloonObject.SetActive(false); ropeObject.SetActive(false); Events["inflateBalloon"].active = false; Events["deflateBalloon"].active = false; Actions["inflateAction"].active = false; Actions["deflateAction"].active = false; } } }
// Awake() - flag this class as don't destroy on load and register delegates void Awake() { // Don't run if Kopernicus isn't compatible if (!CompatibilityChecker.IsCompatible()) { Destroy(this); return; } // Make sure the runtime utility isn't killed DontDestroyOnLoad(this); // Init the runtime logging new Logger("Kopernicus.Runtime").SetAsActive(); // Add handlers GameEvents.onPartUnpack.Add(OnPartUnpack); GameEvents.onLevelWasLoaded.Add(FixCameras); GameEvents.onLevelWasLoaded.Add(delegate(GameScenes scene) { //if (MapView.fetch != null) // MapView.fetch.max3DlineDrawDist = Single.MaxValue; if (scene == GameScenes.SPACECENTER) { PatchFI(); } foreach (CelestialBody body in PSystemManager.Instance.localBodies) { GameObject star = KopernicusStar.GetNearest(body).gameObject; if (body.afg != null) { body.afg.sunLight = star; } if (body.scaledBody.GetComponent <MaterialSetDirection>() != null) { body.scaledBody.GetComponent <MaterialSetDirection>().target = star.transform; } foreach (PQSMod_MaterialSetDirection msd in body.GetComponentsInChildren <PQSMod_MaterialSetDirection>(true)) { msd.target = star.transform; } // Contract Weight if (ContractSystem.ContractWeights != null) { if (body.Has("contractWeight")) { if (ContractSystem.ContractWeights.ContainsKey(body.name)) { ContractSystem.ContractWeights[body.name] = body.Get <Int32>("contractWeight"); } else { ContractSystem.ContractWeights.Add(body.name, body.Get <Int32>("contractWeight")); } } } } foreach (TimeOfDayAnimation anim in Resources.FindObjectsOfTypeAll <TimeOfDayAnimation>()) { anim.target = KopernicusStar.GetNearest(FlightGlobals.GetHomeBody()).gameObject.transform; } #if FALSE foreach (TimeOfDayAnimation anim in Resources.FindObjectsOfTypeAll <TimeOfDayAnimation>()) { anim.gameObject.AddOrGetComponent <KopernicusStarTimeOfDay>(); } foreach (GalaxyCubeControl control in Resources.FindObjectsOfTypeAll <GalaxyCubeControl>()) { control.gameObject.AddOrGetComponent <KopernicusStarGalaxyCubeControl>(); } foreach (SkySphereControl control in Resources.FindObjectsOfTypeAll <SkySphereControl>()) { control.gameObject.AddOrGetComponent <KopernicusStarSkySphereControl>(); } #endif }); GameEvents.onProtoVesselLoad.Add(TransformBodyReferencesOnLoad); GameEvents.onProtoVesselSave.Add(TransformBodyReferencesOnSave); // Update Music Logic if (MusicLogic.fetch != null && FlightGlobals.fetch != null && FlightGlobals.GetHomeBody() != null) { MusicLogic.fetch.flightMusicSpaceAltitude = FlightGlobals.GetHomeBody().atmosphereDepth; } // Log Logger.Default.Log("[Kopernicus] RuntimeUtility Started"); Logger.Default.Flush(); }
void StationaryCamera() { Debug.Log("flightCamera position init: " + flightCamera.transform.position); if (FlightGlobals.ActiveVessel != null) { hasDied = false; vessel = FlightGlobals.ActiveVessel; cameraUp = -FlightGlobals.getGeeForceAtPosition(vessel.GetWorldPos3D()).normalized; if (FlightCamera.fetch.mode == FlightCamera.Modes.ORBITAL || (FlightCamera.fetch.mode == FlightCamera.Modes.AUTO && FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL)) { cameraUp = Vector3.up; } flightCamera.transform.parent = cameraParent.transform; flightCamera.setTarget(null); cameraParent.transform.position = vessel.transform.position + vessel.rigidbody.velocity * Time.fixedDeltaTime; manualPosition = Vector3.zero; hasTarget = (camTarget != null) ? true : false; Vector3 rightAxis; if (referenceMode == ReferenceModes.Surface && vessel.horizontalSrfSpeed > 2) { rightAxis = Quaternion.AngleAxis(-90, vessel.srf_velocity) * cameraUp; } else { rightAxis = Quaternion.AngleAxis(-90, vessel.obt_velocity) * cameraUp; } if (flightCamera.autoMode == FlightCamera.Modes.FREE) { Vector3 cameraUpRef = cameraUp; Vector3.OrthoNormalize(ref rightAxis, ref cameraUpRef); } if (autoFlybyPosition) { setPresetOffset = false; Vector3 velocity = vessel.srf_velocity; if (referenceMode == ReferenceModes.Orbit) { velocity = vessel.obt_velocity; } Vector3 clampedVelocity = Mathf.Clamp((float)vessel.srfSpeed, 0, maxRelV) * velocity.normalized; float clampedSpeed = clampedVelocity.magnitude; float sideDistance = Mathf.Clamp(20 + (clampedSpeed / 10), 20, 150); float distanceAhead = Mathf.Clamp(4 * clampedSpeed, 30, 3500); flightCamera.transform.rotation = Quaternion.LookRotation(vessel.transform.position - flightCamera.transform.position, cameraUp); if (referenceMode == ReferenceModes.Surface && vessel.srfSpeed > 4) { flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.srf_velocity.normalized); } else if (referenceMode == ReferenceModes.Orbit && vessel.obt_speed > 4) { flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.obt_velocity.normalized); } else { flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.vesselTransform.up); } if (flightCamera.mode == FlightCamera.Modes.FREE || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.FREE) { flightCamera.transform.position += (sideDistance * rightAxis) + (15 * cameraUp); } else if (flightCamera.mode == FlightCamera.Modes.ORBITAL || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL) { flightCamera.transform.position += (sideDistance * FlightGlobals.getUpAxis()) + (15 * Vector3.up); } } else if (manualOffset) { setPresetOffset = false; float sideDistance = manualOffsetRight; float distanceAhead = manualOffsetForward; flightCamera.transform.rotation = Quaternion.LookRotation(vessel.transform.position - flightCamera.transform.position, cameraUp); if (referenceMode == ReferenceModes.Surface && vessel.srfSpeed > 4) { flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.srf_velocity.normalized); } else if (referenceMode == ReferenceModes.Orbit && vessel.obt_speed > 4) { flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.obt_velocity.normalized); } else { flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.vesselTransform.up); } if (flightCamera.mode == FlightCamera.Modes.FREE || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.FREE) { flightCamera.transform.position += (sideDistance * rightAxis) + (manualOffsetUp * cameraUp); } else if (flightCamera.mode == FlightCamera.Modes.ORBITAL || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL) { flightCamera.transform.position += (sideDistance * FlightGlobals.getUpAxis()) + (manualOffsetUp * Vector3.up); } } else if (setPresetOffset) { flightCamera.transform.position = presetOffset; //setPresetOffset = false; } initialVelocity = vessel.srf_velocity; initialOrbit = new Orbit(); initialOrbit.UpdateFromStateVectors(vessel.orbit.pos, vessel.orbit.vel, FlightGlobals.currentMainBody, Planetarium.GetUniversalTime()); initialUT = Planetarium.GetUniversalTime(); isStationaryCamera = true; isDefault = false; SetDoppler(); AddAtmoAudioControllers(); } else { Debug.Log("CameraTools: Stationary Camera failed. Active Vessel is null."); } resetPositionFix = flightCamera.transform.position; Debug.Log("flightCamera position post init: " + flightCamera.transform.position); }
public static void RemovePhysicObject(Part p, Transform transf) { FlightGlobals.removePhysicalObject(transf.gameObject); UnityEngine.Object.Destroy(transf.GetComponent<Rigidbody>()); transf.parent = p.transform; }
protected override void on_vessel_launched(Vessel vsl) { base.on_vessel_launched(vsl); if (recipient_node != null) { var construction_node_pos = part.partTransform.TransformPoint(construction_node.position); var construction_node_fwd = part.partTransform.TransformDirection(construction_node.orientation).normalized; var construction_part = recipient_node.owner; var spawn_transform = get_deploy_transform(); Vector3 docking_offset = spawn_transform.position + spawn_transform.TransformDirection(get_deployed_offset()) - construction_node_pos; var docking_node = kit.GetDockingNode(vsl, ConstructDockingNode); if (docking_node == null) { Utils.Message("No suitable attachment node found in \"{0}\" to dock it to the {1}", vsl.GetDisplayName(), construction_part.Title()); return; } FXMonger.Explode(part, construction_node_pos, 0); var docking_part = docking_node.owner; this.Log("Docking {} to {}", docking_part.GetID(), construction_part.GetID()); var old_vessel = construction_part.vessel; // vessels' position and rotation construction_part.vessel.SetPosition(construction_part.vessel.transform.position, true); construction_part.vessel.SetRotation(construction_part.vessel.transform.rotation); docking_part.vessel.SetPosition(docking_part.vessel.transform.position - docking_offset, true); docking_part.vessel.SetRotation(docking_part.vessel.transform.rotation); construction_part.vessel.IgnoreGForces(10); docking_part.vessel.IgnoreGForces(10); if (construction_part == part.parent) { part.decouple(); } else { construction_part.decouple(); } recipient_node.attachedPart = docking_part; recipient_node.attachedPartId = docking_part.flightID; docking_node.attachedPart = construction_part; docking_node.attachedPartId = construction_part.flightID; docking_part.Couple(construction_part); // manage docking ports, if any foreach (var port in construction_part.FindModulesImplementing <ModuleDockingNode>()) { if (port.referenceNode == recipient_node) { port.dockedPartUId = docking_part.persistentId; port.fsm.StartFSM(port.st_preattached); break; } } foreach (var port in docking_part.FindModulesImplementing <ModuleDockingNode>()) { if (port.referenceNode == docking_node) { port.dockedPartUId = construction_part.persistentId; port.fsm.StartFSM(port.st_preattached); break; } } // add fuel lookups construction_part.fuelLookupTargets.Add(docking_part); docking_part.fuelLookupTargets.Add(construction_part); GameEvents.onPartFuelLookupStateChange.Fire(new GameEvents.HostedFromToAction <bool, Part>(true, docking_part, construction_part)); FlightGlobals.ForceSetActiveVessel(construction_part.vessel); FlightInputHandler.SetNeutralControls(); GameEvents.onVesselWasModified.Fire(construction_part.vessel); recipient_node = null; this.Log("Docked {} to {}, new vessel {}", docking_part, construction_part, construction_part.vessel.GetID()); } }
private void PerformScan() { var numLodes = 0; string msg; if (_ani != null && !_ani.isDeployed) { msg = string.Format("Must deploy first!"); ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER); return; } var minAlt = vessel.mainBody.Radius * altModifier; if (altModifier > ResourceUtilities.FLOAT_TOLERANCE && (vessel.altitude < minAlt || vessel.altitude > minAlt * 2d)) { msg = string.Format("Must perform scan at an altitude between {0:0}km and {1:0}km.", minAlt / 1000, minAlt * 2 / 1000); ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER); return; } if (FlightGlobals.currentMainBody == FlightGlobals.GetHomeBody() && !allowHomeBody) { msg = string.Format("There are no resource lodes available on " + FlightGlobals.GetHomeBody().bodyName + "!"); ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER); return; } foreach (var v in FlightGlobals.Vessels) { if (v.mainBody != vessel.mainBody) { continue; } if (v.packed && !v.loaded) { if (v.protoVessel.protoPartSnapshots.Count > 1) { continue; } if (v.protoVessel.protoPartSnapshots[0].partName == lodePart) { numLodes++; } } else { if (v.Parts.Count > 1) { continue; } if (v.FindPartModuleImplementing <ModuleResourceLode>() != null) { numLodes++; } } } if (numLodes >= maxLodes) { msg = string.Format("Too many resource lodes active - Harvest some first!"); ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER); return; } var lode = new LodeData(); lode.name = "Resource Lode"; lode.craftPart = PartLoader.getPartInfoByName(lodePart); lode.vesselType = VesselType.Unknown; lode.body = FlightGlobals.currentMainBody; lode.orbit = null; lode.latitude = RandomizePosition(part.vessel.latitude, lodeRange); lode.longitude = RandomizePosition(part.vessel.longitude, lodeRange); lode.altitude = null; CreateLode(lode); msg = string.Format("A new resource lode has been discovered and added to your map!"); ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER); }
public void FixedUpdate() { if (HighLogic.LoadedSceneIsEditor) { return; } if (engine.type == EngineWrapper.EngineType.NONE || !engine.EngineIgnited) { return; } if (vessel.mainBody.atmosphereContainsOxygen == false || part.vessel.altitude > vessel.mainBody.maxAtmosphereAltitude) { engine.SetThrust(0); return; } #region Inlet float Arearatio, OverallTPR = 0, EngineArea = 0, InletArea = 0; AJEModule e; AJEInlet i; foreach (Part p in vessel.parts) { if (p.Modules.Contains("AJEModule")) { e = (AJEModule)p.Modules["AJEModule"]; EngineArea += (float)(e.aje.areaCore * (1 + e.aje.byprat)); } if (p.Modules.Contains("AJEInlet")) { i = (AJEInlet)p.Modules["AJEInlet"]; if (true) { InletArea += i.Area; OverallTPR += i.Area * i.cosine * i.cosine * i.GetTPR((float)aje.fsmach); } } } if (InletArea > 0) { OverallTPR /= InletArea; } Arearatio = Mathf.Min(InletArea / EngineArea, 1f); aje.eta[2] = Mathf.Clamp(Mathf.Sqrt(Arearatio) * OverallTPR, 0.001f, 1f); Inlet = "Area:" + ((int)(Arearatio * 100f)).ToString() + "% TPR:" + ((int)(OverallTPR * 100f)).ToString() + "%"; #endregion aje.FARps0 = FlightGlobals.getStaticPressure(vessel.altitude, vessel.mainBody); aje.FARts0 = FlightGlobals.getExternalTemperature((float)vessel.altitude, vessel.mainBody) + 273.15f; Environment = (((int)(aje.FARps0 * 100f)) / 100f).ToString() + "atm;" + (((int)(aje.FARts0 * 100f)) / 100f) + "K"; if (usePrat3Curve) { aje.prat[3] = aje.p3p2d = (double)(prat3Curve.Evaluate((float)aje.fsmach)); } aje.u0d = part.vessel.srfSpeed * 3.6d; OverallThrottle = vessel.ctrlState.mainThrottle * engine.thrustPercentage / 100f; if (!useAB) { aje.comPute(); engine.SetThrust(((float)aje.forceNetlb) * 0.004448f); engine.SetIsp((float)aje.isp); Mode = "Cruise " + System.Convert.ToString((int)(OverallThrottle * 100f)) + "%"; } else { if (OverallThrottle <= ABthreshold) { engine.useEngineResponseTime = true; aje.abflag = 0; aje.comPute(); engine.SetThrust(((float)aje.forceNetlb) * 0.004448f / ABthreshold); engine.SetIsp((float)aje.isp); Mode = "Cruise " + System.Convert.ToString((int)(OverallThrottle / ABthreshold * 100f)) + "%"; } else { // only allow instance response when already at max RPM; if the compressor is still spooling up, it's still spooling up. if (engine.currentThrottle > ABthreshold) { engine.useEngineResponseTime = false; } else { engine.useEngineResponseTime = true; } aje.abflag = 1; aje.tt7 = (OverallThrottle - ABthreshold) * (ABmax - ABmin) / (1 - ABthreshold) + ABmin; aje.comPute(); engine.SetThrust(((float)aje.forceNetlb) * 0.004448f / OverallThrottle); engine.SetIsp((float)aje.isp * ABIspMult); Mode = "Afterburner " + System.Convert.ToString((int)((OverallThrottle - ABthreshold) / (1 - ABthreshold) * 100f)) + "%"; } } Mode += " (" + (aje.forceGrosslb * 0.004448f).ToString("N2") + "kN gr)"; if (aje.fireflag > 0.9f && useOverheat) { part.temperature = (aje.fireflag * 2f - 1.2f) * part.maxTemp; } fireflag = aje.fireflag; parttemp = part.temperature; maxtemp = part.maxTemp; // mach = (float)aje.fsmach; }
/// <summary> /// Update for every other tic /// </summary> public override void OnUpdate() { base.OnUpdate(); if (HighLogic.LoadedSceneIsFlight) { bool valid = true; //check for atmosphere if (needsAtmosphere) { valid &= vessel.mainBody.atmosphere; } if (needsOxygen) { valid &= vessel.mainBody.atmosphere && vessel.mainBody.atmosphereContainsOxygen; } //check for water if (needsSubmerged) { valid &= (vessel.mainBody.ocean) && (thrustTransform != null) && (FlightGlobals.getAltitudeAtPos(thrustTransform.position) < 0.0f); } //when all conditions are fulfilled, produce the resource if (valid) { produce(resourceName, amount); } } }
private Vector3 AddGroundEffectForce(Part part, Vector3 originalLift) { Vector3 normal = oceanNormal; // groundPlane.distance and groundDistance are different btw. // groundDistance is measured from an individual part float groundDistance = Single.MaxValue; // say that wings must be within 45 degrees flat towards the ground to have any effect //if (dot > 0.707f) { // Check distance from ocean (if planet has one), sea level is 0 (i think) if (FlightGlobals.currentMainBody.ocean) { groundDistance = Math.Max(FlightGlobals.getAltitudeAtPos(part.transform.position), 0.0f); } // groundPlane.distance is zero if ground is too far away if (NearlyEqual(groundPlane.distance, 0.0f) == false) { // Set ground distance to approximated terrain proximity // If the ocean is closer, then the ocean distance will be used groundDistance = Math.Min(groundDistance, groundPlane.GetDistanceToPoint(part.transform.position)); normal = groundPlane.normal; } if (Vector3.Dot(originalLift, normal) < 0) { // ignore downwards facing wings return(originalLift); } // By now, ground distance has been determined // Convert ground distance to wing spans between 0.0 .. 1.0 groundDistance = Math.Min(1.0f, groundDistance / wingSpan); if (NearlyEqual(groundDistance, 1.0f)) { // not close enough to the ground, return lift unchanged return(originalLift); } // Confirmed wing is in ground effect inGroundEffect = true; // Dot product with surface normal is how aligned the wing is to the ground. // Vertical stabilizers would have a dot product of zero // Horizontal wings will have 1 float horizontalness = Math.Abs(Vector3.Dot(groundDir, part.transform.forward)); // at groundDistance = 1.0, groundEffectMul is 1.0 // as it gets closer to the ground... // at groundDistance = 0.0, groundEffectMul = LiftMultiplier // y = m(x - 1)^2 + 1 //float groundEffectMul = (DefaultLiftMultiplier - 1) // * (float)(Math.Pow(groundDistance - 1.0f, 2.0f)) // + 1; // Induced drag: // get horizontal velocity = velocity - normal * velocity.dot(normal) // normalize horizontal velocity // induced drag = horzVelocity * lift.dot(horzVelocity) Vector3 velocity = part.Rigidbody.velocity; Vector3 horzVelocity = (velocity - normal * Vector3.Dot(velocity, normal)).normalized; Vector3 protoInducedDrag = horzVelocity * Vector3.Dot(originalLift, horzVelocity); Vector3 inducedDrag; float dotInducedDrag = Vector3.Dot(velocity, protoInducedDrag); if (dotInducedDrag < 0) // If drag is pulling us the same way as our velocity, something is wrong! { inducedDrag = Vector3.zero; // dirty, but works I think } else { inducedDrag = protoInducedDrag; } float groundness = horizontalness * (1.0f - groundDistance); groundness *= groundness; // force = -inducedDrag * groundness + (originalLift - inducedDrag) * DefaultLiftMultiplier * groundness; // force = ((originalLift - inducedDrag) * DefaultLiftMultiplier - inducedDrag) * groundness; // The problem with this is that it can lead to negative drag for some reason in certain contexts (often // involving Tweakscale). Simple dirty fix: ignore the inducedDrag vector if it's gonna cause negative drag. // Simple in theory, but there's no good built in way to compare Vector3 objects how I want, so gotta make one. // (See dotInducedDrag and the comparison stuff above.) Vector3 force = -inducedDrag * groundness + (originalLift - inducedDrag) * DefaultLiftMultiplier * groundness; part.Rigidbody.AddForce(force, ForceMode.Force); return(force + originalLift); //Vector3 extraLift = (originalLift - inducedDrag) * DefaultLiftMultiplier * (groundDistance - horizontalness + 1.0f); //Vector3 extraLift = normal * horizontalness * equation; //float totalMag = originalLift.magnitude * DefaultLiftMultiplier; //Vector3 newLift = Vector3.Lerp(normal * totalMag, originalLift, // groundDistance - horizontalness + 1.0f); //part.Rigidbody.AddForce(newLift - originalLift, ForceMode.Force); //part.Rigidbody.AddForce(newLift - originalLift, ForceMode.Force); // return new lift force //return newLift; }
public float StageTimeLeftFullThrottle() { MechJebModuleStageStats stats = core.GetComputerModule <MechJebModuleStageStats>(); stats.RequestUpdate(this); if (stats.vacStats.Length == 0 || stats.atmoStats.Length == 0) { return(0); } float vacTimeLeft = stats.vacStats[stats.vacStats.Length - 1].deltaTime; float atmoTimeLeft = stats.atmoStats[stats.atmoStats.Length - 1].deltaTime; float timeLeft = Mathf.Lerp(vacTimeLeft, atmoTimeLeft, Mathf.Clamp01((float)FlightGlobals.getStaticPressure())); return(timeLeft); }
private float CalculateExposure(Vector3d cameraWorldPos) { staticPressure = (float)(FlightGlobals.getStaticPressure(cameraWorldPos) * KPtoAtms); return(Mathf.Lerp(SkyboxExposure, 0f, staticPressure)); }
public Vessel GetVessel() { return(FlightGlobals.FindVessel(vesselID)); }
void FixedUpdate() { float distanceFromStart = Vector3.Distance(transform.position, startPosition); if (!gameObject.activeInHierarchy) { return; } flightTimeElapsed += TimeWarp.fixedDeltaTime; //calculate flight time for drag purposes if (bulletDrop && FlightGlobals.RefFrameIsRotating) { currentVelocity += FlightGlobals.getGeeForceAtPosition(transform.position) * TimeWarp.fixedDeltaTime; } if (dragType == BulletDragTypes.NumericalIntegration) { Vector3 dragAcc = currentVelocity * currentVelocity.magnitude * (float)FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position), FlightGlobals.getExternalTemperature(transform.position)); dragAcc *= 0.5f; dragAcc /= ballisticCoefficient; currentVelocity -= dragAcc * TimeWarp.fixedDeltaTime; //numerical integration; using Euler is silly, but let's go with it anyway } if (tracerLength == 0) { bulletTrail.SetPosition(0, transform.position + (currentVelocity * tracerDeltaFactor * TimeWarp.fixedDeltaTime / TimeWarp.CurrentRate) - (FlightGlobals.ActiveVessel.rb_velocity * TimeWarp.fixedDeltaTime)); } else { bulletTrail.SetPosition(0, transform.position + ((currentVelocity - sourceOriginalV).normalized * tracerLength)); } if (fadeColor) { FadeColor(); bulletTrail.material.SetColor("_TintColor", currentColor * tracerLuminance); } bulletTrail.SetPosition(1, transform.position); currPosition = gameObject.transform.position; if (distanceFromStart > maxDistance) { //GameObject.Destroy(gameObject); KillBullet(); return; } if (collisionEnabled) { float dist = initialSpeed * TimeWarp.fixedDeltaTime; Ray ray = new Ray(prevPosition, currPosition - prevPosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, dist, 557057)) { bool penetrated = true; float impactVelocity = currentVelocity.magnitude; if (dragType == BulletDragTypes.AnalyticEstimate) { float analyticDragVelAdjustment = (float)FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(currPosition), FlightGlobals.getExternalTemperature(currPosition)); analyticDragVelAdjustment *= flightTimeElapsed * initialSpeed; analyticDragVelAdjustment += 2 * ballisticCoefficient; analyticDragVelAdjustment = 2 * ballisticCoefficient * initialSpeed / analyticDragVelAdjustment; //velocity as a function of time under the assumption of a projectile only acted upon by drag with a constant drag area analyticDragVelAdjustment = analyticDragVelAdjustment - initialSpeed; //since the above was velocity as a function of time, but we need a difference in drag, subtract the initial velocity //the above number should be negative... impactVelocity += analyticDragVelAdjustment; //so add it to the impact velocity if (impactVelocity < 0) { impactVelocity = 0; //clamp the velocity to > 0, since it could drop below 0 if the bullet is fired upwards } //Debug.Log("flight time: " + flightTimeElapsed + " BC: " + ballisticCoefficient + "\ninit speed: " + initialSpeed + " vel diff: " + analyticDragVelAdjustment); } //hitting a vessel Part ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE START////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Part hitPart = null; //determine when bullet collides with a target try{ hitPart = Part.FromGO(hit.rigidbody.gameObject); }catch (NullReferenceException) {} float hitAngle = Vector3.Angle(currentVelocity, -hit.normal); if (hitPart != null) //see if it will ricochet of the part { penetrated = !RicochetOnPart(hitPart, hitAngle, impactVelocity); } else //see if it will ricochet off scenery { float reflectRandom = UnityEngine.Random.Range(-150f, 90f); if (reflectRandom > 90 - hitAngle) { penetrated = false; } } if (hitPart != null && !hitPart.partInfo.name.Contains("Strut")) //when a part is hit, execute damage code (ignores struts to keep those from being abused as armor)(no, because they caused weird bugs :) -BahamutoD) { float heatDamage = (mass / (hitPart.crashTolerance * hitPart.mass)) * impactVelocity * impactVelocity * BDArmorySettings.DMG_MULTIPLIER; //how much heat damage will be applied based on bullet mass, velocity, and part's impact tolerance and mass if (!penetrated) { heatDamage = heatDamage / 8; } if (BDArmorySettings.INSTAKILL) //instakill support, will be removed once mod becomes officially MP { heatDamage = (float)hitPart.maxTemp + 100; //make heat damage equal to the part's max temperture, effectively instakilling any part it hits } if (BDArmorySettings.DRAW_DEBUG_LINES) { Debug.Log("Hit! damage applied: " + heatDamage); //debugging stuff } if (hitPart.vessel != sourceVessel) { hitPart.temperature += heatDamage; //apply heat damage to the hit part. } float overKillHeatDamage = (float)(hitPart.temperature - hitPart.maxTemp); if (overKillHeatDamage > 0) //if the part is destroyed by overheating, we want to add the remaining heat to attached parts. This prevents using tiny parts as armor { overKillHeatDamage *= hitPart.crashTolerance; //reset to raw damage float numConnectedParts = hitPart.children.Count; if (hitPart.parent != null) { numConnectedParts++; overKillHeatDamage /= numConnectedParts; hitPart.parent.temperature += overKillHeatDamage / (hitPart.parent.crashTolerance * hitPart.parent.mass); for (int i = 0; i < hitPart.children.Count; i++) { hitPart.children[i].temperature += overKillHeatDamage / hitPart.children[i].crashTolerance; } } else { overKillHeatDamage /= numConnectedParts; for (int i = 0; i < hitPart.children.Count; i++) { hitPart.children[i].temperature += overKillHeatDamage / hitPart.children[i].crashTolerance; } } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE END//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //hitting a Building DestructibleBuilding hitBuilding = null; try{ hitBuilding = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>(); } catch (NullReferenceException) {} if (hitBuilding != null && hitBuilding.IsIntact) { float damageToBuilding = mass * initialSpeed * initialSpeed * BDArmorySettings.DMG_MULTIPLIER / 12000; if (!penetrated) { damageToBuilding = damageToBuilding / 8; } hitBuilding.AddDamage(damageToBuilding); if (hitBuilding.Damage > hitBuilding.impactMomentumThreshold) { hitBuilding.Demolish(); } if (BDArmorySettings.DRAW_DEBUG_LINES) { Debug.Log("bullet hit destructible building! Damage: " + (damageToBuilding).ToString("0.00") + ", total Damage: " + hitBuilding.Damage); } } if (hitPart == null || (hitPart != null && hitPart.vessel != sourceVessel)) { if (!penetrated && !hasBounced) { //ricochet hasBounced = true; if (BDArmorySettings.BULLET_HITS) { BulletHitFX.CreateBulletHit(hit.point, hit.normal, true); } tracerStartWidth /= 2; tracerEndWidth /= 2; transform.position = hit.point; currentVelocity = Vector3.Reflect(currentVelocity, hit.normal); currentVelocity = (hitAngle / 150) * currentVelocity * 0.65f; Vector3 randomDirection = UnityEngine.Random.rotation * Vector3.one; currentVelocity = Vector3.RotateTowards(currentVelocity, randomDirection, UnityEngine.Random.Range(0f, 5f) * Mathf.Deg2Rad, 0); } else { if (BDArmorySettings.BULLET_HITS) { BulletHitFX.CreateBulletHit(hit.point, hit.normal, false); } if (bulletType == PooledBulletTypes.Explosive) { ExplosionFX.CreateExplosion(hit.point, radius, blastPower, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath); } //GameObject.Destroy(gameObject); //destroy bullet on collision KillBullet(); return; } } } /* * if(isUnderwater) * { * if(FlightGlobals.getAltitudeAtPos(transform.position) > 0) * { * isUnderwater = false; * } * else * { * rigidbody.AddForce(-rigidbody.velocity * 0.15f); * } * } * else * { * if(FlightGlobals.getAltitudeAtPos(transform.position) < 0) * { * isUnderwater = true; * //FXMonger.Splash(transform.position, 1); * //make a custom splash here * } * } */ } if (bulletType == PooledBulletTypes.Explosive && airDetonation && distanceFromStart > detonationRange) { //detonate ExplosionFX.CreateExplosion(transform.position, radius, blastPower, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath); //GameObject.Destroy(gameObject); //destroy bullet on collision KillBullet(); return; } prevPosition = currPosition; //move bullet transform.position += currentVelocity * Time.fixedDeltaTime; }
/// <summary> /// Send new control data to the active vessel. /// Checks the vesselSync value to prevent using old ControlPackets after vessel change. /// </summary> /// <param name="CPacket">Control data</param> /// <param name="sync">Current VesselData sync value</param> public void ControlsReceived(ControlPacket CPacket, byte sync) { if (CPacket.vesselSync == sync) { //Detect vessel change _vControls.vesselSync = CPacket.vesselSync; bool vesselChanged = _vControls.vesselSync != _vControlsOld.vesselSync; _vControlsOld.vesselSync = _vControls.vesselSync; _vControls.SAS = BitMathByte(CPacket.MainControls, 7); _vControls.RCS = BitMathByte(CPacket.MainControls, 6); _vControls.Lights = BitMathByte(CPacket.MainControls, 5); _vControls.Gear = BitMathByte(CPacket.MainControls, 4); _vControls.Brakes = BitMathByte(CPacket.MainControls, 3); _vControls.Precision = BitMathByte(CPacket.MainControls, 2); _vControls.Abort = BitMathByte(CPacket.MainControls, 1); _vControls.Stage = BitMathByte(CPacket.MainControls, 0); _vControls.Pitch = (float)CPacket.Pitch / 1000.0F; _vControls.Roll = (float)CPacket.Roll / 1000.0F; _vControls.Yaw = (float)CPacket.Yaw / 1000.0F; _vControls.TX = (float)CPacket.TX / 1000.0F; _vControls.TY = (float)CPacket.TY / 1000.0F; _vControls.TZ = (float)CPacket.TZ / 1000.0F; _vControls.WheelSteer = (float)CPacket.WheelSteer / 1000.0F; _vControls.Throttle = (float)CPacket.Throttle / 1000.0F; _vControls.WheelThrottle = (float)CPacket.WheelThrottle / 1000.0F; _vControls.SASMode = (int)CPacket.NavballSASMode & 0x0F; _vControls.SpeedMode = (int)(CPacket.NavballSASMode >> 4); _vControls.UiMode = (int)CPacket.Mode & 0x0F; _vControls.CameraMode = (int)(CPacket.Mode >> 4); _vControls.OpenMenu = BitMathByte(CPacket.AdditionalControlByte1, 0); _vControls.OpenMap = BitMathByte(CPacket.AdditionalControlByte1, 1); for (int j = 1; j <= 10; j++) { _vControls.ControlGroup[j] = BitMathUshort(CPacket.ControlGroup, j); } //if (FlightInputHandler.RCSLock != VControls.RCS) if (_vControls.RCS != _vControlsOld.RCS || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, _vControls.RCS); _vControlsOld.RCS = _vControls.RCS; //ScreenMessages.PostScreenMessage("RCS: " + VControls.RCS.ToString(), 10f, KSPIOScreenStyle); } //if (ActiveVessel.ctrlState.killRot != VControls.SAS) if (_vControls.SAS != _vControlsOld.SAS || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, _vControls.SAS); _vControlsOld.SAS = _vControls.SAS; //ScreenMessages.PostScreenMessage("SAS: " + VControls.SAS.ToString(), 10f, KSPIOScreenStyle); } if (_vControls.Lights != _vControlsOld.Lights || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Light, _vControls.Lights); _vControlsOld.Lights = _vControls.Lights; } if (_vControls.Gear != _vControlsOld.Gear || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, _vControls.Gear); _vControlsOld.Gear = _vControls.Gear; } if (_vControls.Brakes != _vControlsOld.Brakes || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, _vControls.Brakes); _vControlsOld.Brakes = _vControls.Brakes; } if (_vControls.Abort != _vControlsOld.Abort || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Abort, _vControls.Abort); _vControlsOld.Abort = _vControls.Abort; } if (_vControls.Stage != _vControlsOld.Stage || vesselChanged) { if (_vControls.Stage) { StageManager.ActivateNextStage(); } _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Stage, _vControls.Stage); _vControlsOld.Stage = _vControls.Stage; } //================ control groups if (_vControls.ControlGroup[1] != _vControlsOld.ControlGroup[1] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom01, _vControls.ControlGroup[1]); _vControlsOld.ControlGroup[1] = _vControls.ControlGroup[1]; } if (_vControls.ControlGroup[2] != _vControlsOld.ControlGroup[2] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom02, _vControls.ControlGroup[2]); _vControlsOld.ControlGroup[2] = _vControls.ControlGroup[2]; } if (_vControls.ControlGroup[3] != _vControlsOld.ControlGroup[3] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom03, _vControls.ControlGroup[3]); _vControlsOld.ControlGroup[3] = _vControls.ControlGroup[3]; } if (_vControls.ControlGroup[4] != _vControlsOld.ControlGroup[4] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom04, _vControls.ControlGroup[4]); _vControlsOld.ControlGroup[4] = _vControls.ControlGroup[4]; } if (_vControls.ControlGroup[5] != _vControlsOld.ControlGroup[5] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom05, _vControls.ControlGroup[5]); _vControlsOld.ControlGroup[5] = _vControls.ControlGroup[5]; } if (_vControls.ControlGroup[6] != _vControlsOld.ControlGroup[6] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom06, _vControls.ControlGroup[6]); _vControlsOld.ControlGroup[6] = _vControls.ControlGroup[6]; } if (_vControls.ControlGroup[7] != _vControlsOld.ControlGroup[7] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom07, _vControls.ControlGroup[7]); _vControlsOld.ControlGroup[7] = _vControls.ControlGroup[7]; } if (_vControls.ControlGroup[8] != _vControlsOld.ControlGroup[8] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom08, _vControls.ControlGroup[8]); _vControlsOld.ControlGroup[8] = _vControls.ControlGroup[8]; } if (_vControls.ControlGroup[9] != _vControlsOld.ControlGroup[9] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom09, _vControls.ControlGroup[9]); _vControlsOld.ControlGroup[9] = _vControls.ControlGroup[9]; } if (_vControls.ControlGroup[10] != _vControlsOld.ControlGroup[10] || vesselChanged) { _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom10, _vControls.ControlGroup[10]); _vControlsOld.ControlGroup[10] = _vControls.ControlGroup[10]; } //Set sas mode if (_vControls.SASMode != _vControlsOld.SASMode || vesselChanged) { if (_vControls.SASMode != 0 && _vControls.SASMode < 11) { if (!_activeVessel.Autopilot.CanSetMode((VesselAutopilot.AutopilotMode)(_vControls.SASMode - 1))) { ScreenMessages.PostScreenMessage("[KSPEthernetIO]: SAS mode " + _vControls.SASMode.ToString() + " not avalible"); } else { _activeVessel.Autopilot.SetMode((VesselAutopilot.AutopilotMode)_vControls.SASMode - 1); } } _vControlsOld.SASMode = _vControls.SASMode; } //set navball mode if (_vControls.SpeedMode != _vControlsOld.SpeedMode || vesselChanged) { if (!((_vControls.SpeedMode == 0) || ((_vControls.SpeedMode == 3) && !TargetExists()))) { FlightGlobals.SetSpeedMode((FlightGlobals.SpeedDisplayModes)(_vControls.SpeedMode - 1)); } _vControlsOld.SpeedMode = _vControls.SpeedMode; } if (Math.Abs(_vControls.Pitch) > Settings.SASTol || Math.Abs(_vControls.Roll) > Settings.SASTol || Math.Abs(_vControls.Yaw) > Settings.SASTol) { if ((_activeVessel.ActionGroups[KSPActionGroup.SAS]) && (_wasSASOn == false)) { _wasSASOn = true; _activeVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, false); } } else { if (_wasSASOn == true) { _wasSASOn = false; _activeVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true); } } if (_vControlsOld.UiMode != _vControls.UiMode || vesselChanged) { if (FlightUIModeController.Instance != null) { switch (_vControls.UiMode) { case 0: FlightUIModeController.Instance.SetMode(FlightUIMode.STAGING); break; case 1: FlightUIModeController.Instance.SetMode(FlightUIMode.DOCKING); break; case 2: FlightUIModeController.Instance.SetMode(FlightUIMode.MAPMODE); break; default: break; } _vControlsOld.UiMode = _vControls.UiMode; } } if (_vControlsOld.CameraMode != _vControls.CameraMode || vesselChanged) { if (FlightCamera.fetch != null) { switch (_vControls.CameraMode) { case 0: FlightCamera.fetch.setMode(FlightCamera.Modes.AUTO); break; case 1: FlightCamera.fetch.setMode(FlightCamera.Modes.FREE); break; case 2: FlightCamera.fetch.setMode(FlightCamera.Modes.ORBITAL); break; case 3: FlightCamera.fetch.setMode(FlightCamera.Modes.CHASE); break; case 4: FlightCamera.fetch.setMode(FlightCamera.Modes.LOCKED); break; default: break; } _vControlsOld.CameraMode = _vControls.CameraMode; } } if (_vControlsOld.OpenMenu != _vControls.OpenMenu || vesselChanged) { if (_vControls.OpenMenu) { PauseMenu.Display(); } else { PauseMenu.Close(); } _vControlsOld.OpenMenu = _vControls.OpenMenu; } if (_vControlsOld.OpenMap != _vControls.OpenMap || vesselChanged) { if (_vControls.OpenMap) { MapView.EnterMapView(); } else { MapView.ExitMapView(); } _vControlsOld.OpenMap = _vControls.OpenMap; } } }
/// <summary> /// Updates this instance /// </summary> void LateUpdate() { // Set precision sunRotationPrecision = MapView.MapIsEnabled ? sunRotationPrecisionMapView : sunRotationPrecisionDefault; // Apply light settings Vector3d localSpace = ScaledSpace.ScaledToLocalSpace(target.position); if (light) { light.color = shifter.sunlightColor; light.intensity = shifter.intensityCurve.Evaluate((Single)Vector3d.Distance(sun.position, localSpace)); light.shadowStrength = shifter.sunlightShadowStrength; } // Patch the ScaledSpace light if (scaledSunLight) { scaledSunLight.color = shifter.scaledSunlightColor; scaledSunLight.intensity = shifter.scaledIntensityCurve.Evaluate((Single)Vector3d.Distance(ScaledSpace.LocalToScaledSpace(sun.position), target.position)); } if (HighLogic.LoadedSceneIsFlight && iva?.GetComponent <Light>()) { iva.GetComponent <Light>().color = shifter.IVASunColor; iva.GetComponent <Light>().intensity = shifter.ivaIntensityCurve.Evaluate((Single)Vector3d.Distance(sun.position, localSpace)); } // Set SunFlare color lensFlare.sunFlare.color = shifter.sunLensFlareColor; // Set other stuff lensFlare.AU = shifter.AU; lensFlare.brightnessCurve = shifter.brightnessCurve.Curve; lensFlare.sun = sun; lensFlare.target = target; // States Boolean lightsOn = (HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneHasPlanetarium || HighLogic.LoadedScene == GameScenes.SPACECENTER); light.enabled = shifter.givesOffLight && lightsOn; lensFlare.sunFlare.enabled = shifter.givesOffLight && lightsOn; sunFlare.enabled = false; if (useLocalSpaceSunLight && Sun.Instance.useLocalSpaceSunLight) { scaledSunLight.enabled = shifter.givesOffLight && lightsOn; } if (Current != null && Current.lensFlare != null) { SunFlare.Instance = Current.lensFlare; } // Update Scaled Space Light if (!useLocalSpaceSunLight) { return; } if (FlightGlobals.currentMainBody == null || FlightGlobals.currentMainBody == sun) { localTime = 1f; } else { Double targetAltitude = FlightGlobals.getAltitudeAtPos(localSpace, FlightGlobals.currentMainBody); if (targetAltitude < 0) { targetAltitude = 0; } Double horizonAngle = Math.Acos(FlightGlobals.currentMainBody.Radius / (FlightGlobals.currentMainBody.Radius + targetAltitude)); Single horizonScalar = -Mathf.Sin((Single)horizonAngle); Single dayNightRatio = 1f - Mathf.Abs(horizonScalar); Single fadeStartAtAlt = horizonScalar + fadeStart * dayNightRatio; Single fadeEndAtAlt = horizonScalar - fadeEnd * dayNightRatio; localTime = Vector3.Dot(-FlightGlobals.getUpAxis(localSpace), transform.forward); light.intensity = Mathf.Lerp(0f, light.intensity, Mathf.InverseLerp(fadeEndAtAlt, fadeStartAtAlt, localTime)); } }
public void SetNavMode(FlightGlobals.SpeedDisplayModes navMode) { FlightGlobals.SetSpeedMode(navMode); }
/// <summary> /// The flight integrator doesn't seem to update the EVA kerbal's position or velocity for about 0.95s of real-time for some unknown reason (this seems fairly constant regardless of time-control or FPS). /// </summary> /// <param name="kerbal">The kerbal on EVA.</param> /// <param name="realTime">The amount of real-time to manually update for.</param> IEnumerator ManuallyMoveKerbalEVACoroutine(KerbalEVA kerbal, Vector3 velocity, float realTime = 1f) { if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.KerbalSafety]: Manually setting position of " + kerbal.vessel.vesselName + " for " + realTime + "s of real-time."); } if (!evaKerbalsToMonitor.Contains(kerbal)) { evaKerbalsToMonitor.Add(kerbal); } var gee = (Vector3)FlightGlobals.getGeeForceAtPosition(kerbal.transform.position); var verticalSpeed = Vector3.Dot(-gee.normalized, velocity); float verticalSpeedAdjustment = 0f; var position = kerbal.vessel.GetWorldPos3D(); if (kerbal.vessel.radarAltitude + verticalSpeed * Time.fixedDeltaTime < 2f) // Crashed into terrain, explode upwards. { if (BDArmorySettings.DRAW_DEBUG_LABELS) { verticalSpeedAdjustment = 3f * (float)gee.magnitude - verticalSpeed; } velocity = Vector3.ProjectOnPlane(velocity, -gee.normalized) - 3f * (gee + UnityEngine.Random.onUnitSphere * 0.3f * gee.magnitude); position += (2f - (float)kerbal.vessel.radarAltitude) * -gee.normalized; kerbal.vessel.SetPosition(position); // Put the kerbal back at just above gound level. kerbal.vessel.Landed = false; } else { velocity += 1.5f * -(gee + UnityEngine.Random.onUnitSphere * 0.3f * gee.magnitude); if (BDArmorySettings.DRAW_DEBUG_LABELS) { verticalSpeedAdjustment = 1.5f * (float)gee.magnitude; } } verticalSpeed = Vector3.Dot(-gee.normalized, velocity); kerbal.vessel.SetRotation(UnityEngine.Random.rotation); kerbal.vessel.rootPart.AddTorque(UnityEngine.Random.onUnitSphere * UnityEngine.Random.Range(1, 2)); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.KerbalSafety]: Setting " + kerbal.vessel.vesselName + "'s position to " + position.ToString("0.00") + " (" + kerbal.vessel.GetWorldPos3D().ToString("0.00") + ", altitude: " + kerbal.vessel.radarAltitude.ToString("0.00") + ") and velocity to " + velocity.magnitude.ToString("0.00") + " (" + verticalSpeed.ToString("0.00") + "m/s vertically, adjusted by " + verticalSpeedAdjustment.ToString("0.00") + "m/s)"); } var startTime = Time.realtimeSinceStartup; kerbal.vessel.rootPart.SetDetectCollisions(false); while (kerbal != null && kerbal.isActiveAndEnabled && kerbal.vessel != null && kerbal.vessel.isActiveAndEnabled && Time.realtimeSinceStartup - startTime < realTime) { // Note: 0.968f gives a reduction in speed to ~20% over 1s. if (verticalSpeed < 0f && kerbal.vessel.radarAltitude + verticalSpeed * (realTime - (Time.realtimeSinceStartup - startTime)) < 100f) { velocity = velocity * 0.968f + gee * verticalSpeed / 10f * Time.fixedDeltaTime; if (BDArmorySettings.DRAW_DEBUG_LABELS) { verticalSpeedAdjustment = Vector3.Dot(-gee.normalized, gee * verticalSpeed / 10f * Time.fixedDeltaTime); } } else { velocity = velocity * 0.968f + gee * Time.fixedDeltaTime; if (BDArmorySettings.DRAW_DEBUG_LABELS) { verticalSpeedAdjustment = Vector3.Dot(-gee.normalized, gee * Time.fixedDeltaTime); } } verticalSpeed = Vector3.Dot(-gee.normalized, velocity); position += velocity * Time.fixedDeltaTime - FloatingOrigin.Offset; kerbal.vessel.IgnoreGForces(1); kerbal.vessel.IgnoreSpeed(1); kerbal.vessel.SetPosition(position); kerbal.vessel.SetWorldVelocity(velocity + Krakensbane.GetLastCorrection()); yield return(new WaitForFixedUpdate()); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.KerbalSafety]: Setting " + kerbal.vessel.vesselName + "'s position to " + position.ToString("0.00") + " (" + kerbal.vessel.GetWorldPos3D().ToString("0.00") + ", altitude: " + kerbal.vessel.radarAltitude.ToString("0.00") + ") and velocity to " + velocity.magnitude.ToString("0.00") + " (" + kerbal.vessel.Velocity().magnitude.ToString("0.00") + ", " + verticalSpeed.ToString("0.00") + "m/s vertically, adjusted by " + verticalSpeedAdjustment.ToString("0.00") + "m/s)." + " (offset: " + !FloatingOrigin.Offset.IsZero() + ", frameVel: " + !Krakensbane.GetFrameVelocity().IsZero() + ")" + " " + Krakensbane.GetFrameVelocityV3f().ToString("0.0") + ", corr: " + Krakensbane.GetLastCorrection().ToString("0.0")); } } if (kerbal != null && kerbal.vessel != null) { kerbal.vessel.rootPart.SetDetectCollisions(true); } if (BDArmorySettings.DRAW_DEBUG_LABELS) { for (int count = 0; kerbal != null && kerbal.isActiveAndEnabled && kerbal.vessel != null && kerbal.vessel.isActiveAndEnabled && count < 10; ++count) { yield return(new WaitForFixedUpdate()); Debug.Log("[BDArmory.KerbalSafety]: Tracking " + kerbal.vessel.vesselName + "'s position to " + kerbal.vessel.GetWorldPos3D().ToString("0.00") + " (altitude: " + kerbal.vessel.radarAltitude.ToString("0.00") + ") and velocity to " + kerbal.vessel.Velocity().magnitude.ToString("0.00") + " (" + kerbal.vessel.verticalSpeed.ToString("0.00") + "m/s vertically." + " (offset: " + !FloatingOrigin.Offset.IsZero() + ", frameVel: " + !Krakensbane.GetFrameVelocity().IsZero() + ")" + " " + Krakensbane.GetFrameVelocityV3f().ToString("0.0") + ", corr: " + Krakensbane.GetLastCorrection().ToString("0.0")); } } }