/// <summary>Check whether there are commands that can be removed from the flight computer command queue (when their delay time has elapsed).</summary> /// <remarks>This is done during the Update() phase of the game engine. <see cref="OnUpdate"/> method.</remarks> private void PopCommand() { // something in command queue? if (_commandQueue.Count <= 0) { return; } // Can come out of time warp even if ship is not powered; workaround for KSP 0.24 power consumption bug if (RTSettings.Instance.ThrottleTimeWarp && TimeWarp.CurrentRate > 4.0f) { var time = TimeWarp.deltaTime; foreach (var dc in _commandQueue.TakeWhile(c => c.TimeStamp <= RTUtil.GameTime + (2 * time + 1.0))) { var message = new ScreenMessage(Localizer.Format("#RT_FC_msg1"), 4.0f, ScreenMessageStyle.UPPER_LEFT); //"[Flight Computer]: Throttling back time warp..." while ((2 * TimeWarp.deltaTime + 1.0) > (Math.Max(dc.TimeStamp - RTUtil.GameTime, 0) + dc.ExtraDelay) && TimeWarp.CurrentRate > 1.0f) // { TimeWarp.SetRate(TimeWarp.CurrentRateIndex - 1, true); ScreenMessages.PostScreenMessage(message); } } } // Proceed the extraDelay for every command where the normal delay is over foreach (var dc in _commandQueue.Where(s => s.Delay == 0).ToList()) { // Use time decrement instead of comparing scheduled time, in case we later want to // reinstate event clocks stopping under certain conditions if (dc.ExtraDelay > 0) { //issue: deltaTime is floating point -/+0.001, not great for long-term time-senitive operation if (dc.ExtraDelayScheduledTimeStamp > RTUtil.GameTime) { dc.ExtraDelay = dc.ExtraDelayScheduledTimeStamp - RTUtil.GameTime; } else //fallback { dc.ExtraDelay -= TimeWarp.deltaTime; } } else { if (SignalProcessor.Powered) { // Note: depending on implementation, dc.Pop() may execute the event if (dc.Pop(this)) { _activeCommands[dc.Priority] = dc; if (OnNewCommandPop != null) { OnNewCommandPop.Invoke(); } } } else { string message = Localizer.Format("#RT_FC_msg2", dc.ShortName);//$"[Flight Computer]: Out of power, cannot run \"{}\" on schedule." ScreenMessages.PostScreenMessage(new ScreenMessage( message, 4.0f, ScreenMessageStyle.UPPER_LEFT)); } _commandQueue.Remove(dc); UpdateLastTarget(); } } }
private void Update() { safeDisplay = display; ignoreChatInput = false; if (chatButtonHighlighted && display) { chatButtonHighlighted = false; } if (chatLocked && !display) { chatLocked = false; InputLockManager.RemoveControlLock(DMP_CHAT_LOCK); } if (workerEnabled) { //Handle leave event if (!leaveEventHandled) { if (selectedChannel != null) { using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.LEAVE); mw.Write <string>(Settings.fetch.playerName); mw.Write <string>(selectedChannel); NetworkWorker.fetch.SendChatMessage(mw.GetMessageBytes()); } if (joinedChannels.Contains(selectedChannel)) { joinedChannels.Remove(selectedChannel); } selectedChannel = null; selectedPMChannel = null; } if (selectedPMChannel != null) { if (joinedPMChannels.Contains(selectedPMChannel)) { joinedPMChannels.Remove(selectedPMChannel); } selectedChannel = null; selectedPMChannel = null; } leaveEventHandled = true; } //Handle send event if (!sendEventHandled) { if (sendText != "") { if (!sendText.StartsWith("/") || sendText.StartsWith("//")) { if (sendText.StartsWith("//")) { sendText = sendText.Substring(1); } if (selectedChannel == null && selectedPMChannel == null) { //Sending a global chat message using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.CHANNEL_MESSAGE); mw.Write <string>(Settings.fetch.playerName); //Global channel name is empty string. mw.Write <string>(""); mw.Write <string>(sendText); NetworkWorker.fetch.SendChatMessage(mw.GetMessageBytes()); } } if (selectedChannel != null) { using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.CHANNEL_MESSAGE); mw.Write <string>(Settings.fetch.playerName); mw.Write <string>(selectedChannel); mw.Write <string>(sendText); NetworkWorker.fetch.SendChatMessage(mw.GetMessageBytes()); } } if (selectedPMChannel != null) { using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.PRIVATE_MESSAGE); mw.Write <string>(Settings.fetch.playerName); mw.Write <string>(selectedPMChannel); mw.Write <string>(sendText); NetworkWorker.fetch.SendChatMessage(mw.GetMessageBytes()); } } } else { //Handle command if (sendText.StartsWith("/join ") && sendText.Length > 7) { string channelName = sendText.Substring(6); if (channelName != "" || channelName != "Global") { DarkLog.Debug("Joining channel " + channelName); joinedChannels.Add(channelName); selectedChannel = channelName; selectedPMChannel = null; using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)ChatMessageType.JOIN); mw.Write <string>(Settings.fetch.playerName); mw.Write <string>(channelName); NetworkWorker.fetch.SendChatMessage(mw.GetMessageBytes()); } } else { ScreenMessages.PostScreenMessage("Couln't join '" + channelName + "', channel name not valid!", 5f, ScreenMessageStyle.UPPER_CENTER); } } if (sendText.StartsWith("/query ") && sendText.Length > 8) { string playerName = sendText.Substring(7); bool playerFound = false; if (playerName != consoleIdentifier) { foreach (PlayerStatus ps in PlayerStatusWorker.fetch.playerStatusList) { if (ps.playerName == playerName) { playerFound = true; } } } else { //Make sure we can always query the server. playerFound = true; } if (playerFound) { DarkLog.Debug("Starting query with " + playerName); joinedPMChannels.Add(playerName); selectedChannel = null; selectedPMChannel = playerName; } else { DarkLog.Debug("Couln't start query with '" + playerName + "', player not found!"); ScreenMessages.PostScreenMessage("Couln't start query with '" + playerName + "', player not found!", 5f, ScreenMessageStyle.UPPER_CENTER); } } if (sendText == "/part" || sendText == "/leave") { leaveEventHandled = false; } if (sendText == "/ping") { NetworkWorker.fetch.SendPingRequest(); } if (sendText == "/motd") { NetworkWorker.fetch.SendMotdRequest(); } } } sendText = ""; sendEventHandled = true; } //Handle join messages while (newJoinMessages.Count > 0) { JoinLeaveMessage jlm = newJoinMessages.Dequeue(); if (!playerChannels.ContainsKey(jlm.fromPlayer)) { playerChannels.Add(jlm.fromPlayer, new List <string>()); } if (!playerChannels[jlm.fromPlayer].Contains(jlm.channel)) { playerChannels[jlm.fromPlayer].Add(jlm.channel); } } //Handle leave messages while (newLeaveMessages.Count > 0) { JoinLeaveMessage jlm = newLeaveMessages.Dequeue(); if (playerChannels.ContainsKey(jlm.fromPlayer)) { if (playerChannels[jlm.fromPlayer].Contains(jlm.channel)) { playerChannels[jlm.fromPlayer].Remove(jlm.channel); } if (playerChannels[jlm.fromPlayer].Count == 0) { playerChannels.Remove(jlm.fromPlayer); } } } //Handle channel messages while (newChannelMessages.Count > 0) { ChannelEntry ce = newChannelMessages.Dequeue(); if (!channelMessages.ContainsKey(ce.channel)) { channelMessages.Add(ce.channel, new List <string>()); } //Highlight if the channel isn't selected. if (selectedChannel != null && ce.channel == "") { if (!highlightChannel.Contains(ce.channel)) { highlightChannel.Add(ce.channel); } } if (ce.channel != selectedChannel && ce.channel != "") { if (!highlightChannel.Contains(ce.channel)) { highlightChannel.Add(ce.channel); } } //Move the bar to the bottom on a new message if (selectedChannel == null && selectedPMChannel == null && ce.channel == "") { chatScrollPos.y = float.PositiveInfinity; } if (selectedChannel != null && selectedPMChannel == null && ce.channel == selectedChannel) { chatScrollPos.y = float.PositiveInfinity; } channelMessages[ce.channel].Add(ce.fromPlayer + ": " + ce.message); } //Handle private messages while (newPrivateMessages.Count > 0) { PrivateEntry pe = newPrivateMessages.Dequeue(); if (pe.fromPlayer != Settings.fetch.playerName) { if (!privateMessages.ContainsKey(pe.fromPlayer)) { privateMessages.Add(pe.fromPlayer, new List <string>()); } //Highlight if the player isn't selected if (!joinedPMChannels.Contains(pe.fromPlayer)) { joinedPMChannels.Add(pe.fromPlayer); } if (selectedPMChannel != pe.fromPlayer) { if (!highlightPM.Contains(pe.fromPlayer)) { highlightPM.Add(pe.fromPlayer); } } } //Move the bar to the bottom on a new message if (selectedPMChannel != null && selectedChannel == null && (pe.fromPlayer == selectedPMChannel || pe.fromPlayer == Settings.fetch.playerName)) { chatScrollPos.y = float.PositiveInfinity; } if (pe.fromPlayer != Settings.fetch.playerName) { privateMessages[pe.fromPlayer].Add(pe.fromPlayer + ": " + pe.message); } else { privateMessages[pe.toPlayer].Add(pe.fromPlayer + ": " + pe.message); } } while (disconnectingPlayers.Count > 0) { string disconnectingPlayer = disconnectingPlayers.Dequeue(); if (playerChannels.ContainsKey(disconnectingPlayer)) { playerChannels.Remove(disconnectingPlayer); } if (joinedPMChannels.Contains(disconnectingPlayer)) { joinedPMChannels.Remove(disconnectingPlayer); } if (highlightPM.Contains(disconnectingPlayer)) { highlightPM.Remove(disconnectingPlayer); } if (privateMessages.ContainsKey(disconnectingPlayer)) { privateMessages.Remove(disconnectingPlayer); } } } }
public static void HUDMessage(string sMessage, float fDuration = 10f, int iStyle = 2) { ScreenMessageStyle smsStyle = (ScreenMessageStyle)iStyle; ScreenMessages.PostScreenMessage(sMessage, fDuration, smsStyle); }
private void WarpdriveCharging() { double currentExoticMatter = 0; double maxExoticMatter = 0; part.GetConnectedResourceTotals(exoticResourceDefinition.id, out currentExoticMatter, out maxExoticMatter); if (IsCharging) { double powerDraw = CheatOptions.InfiniteElectricity ? (maxExoticMatter - currentExoticMatter) / 0.001 : Math.Max(minPowerRequirementForLightSpeed, Math.Min((maxExoticMatter - currentExoticMatter) / 0.001, getStableResourceSupply(FNResourceManager.FNRESOURCE_MEGAJOULES))); double power_returned = CheatOptions.InfiniteElectricity ? powerDraw : consumeFNResource(powerDraw * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime; if (power_returned < 0.99 * minPowerRequirementForLightSpeed) { insufficientPowerTimeout--; } else { insufficientPowerTimeout = 10; } if (insufficientPowerTimeout < 0) { insufficientPowerTimeout--; ScreenMessages.PostScreenMessage("Not enough MW power to initiate stable warp field!", 5.0f, ScreenMessageStyle.UPPER_CENTER); StopCharging(); return; } if (currentExoticMatter < exotic_power_required) { part.RequestResource(InterstellarResourcesConfiguration.Instance.ExoticMatter, -power_returned * 0.001 * TimeWarp.fixedDeltaTime); } if (!CheatOptions.IgnoreMaxTemperature) { supplyFNResource(-power_returned * 0.999 * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT); } } if (!IsEnabled) { if (currentExoticMatter < exotic_power_required) { double electrical_current_pct = 100.0 * currentExoticMatter / exotic_power_required; DriveStatus = String.Format("Charging: ") + electrical_current_pct.ToString("0.00") + String.Format("%"); } else { DriveStatus = "Ready."; } warp_effect2_renderer.enabled = false; warp_effect1_renderer.enabled = false; } else { DriveStatus = "Active."; ; warp_effect2_renderer.enabled = true; warp_effect1_renderer.enabled = true; } }
private void MainWindow(int id) { Trajectory traj = Trajectory.fetch; var lastPatch = traj.patches.LastOrDefault(); GUILayout.BeginHorizontal(); Settings.fetch.DisplayTrajectories = GUILayout.Toggle(Settings.fetch.DisplayTrajectories, "Display trajectory", GUILayout.Width(125)); // check that we have patched conics. If not, apologize to the user and return. if (Settings.fetch.DisplayTrajectories && !isPatchedConicsAvailable()) { ScreenMessages.PostScreenMessage( "Can't show trajectory because patched conics are not available." + " Please update your tracking station facility."); Settings.fetch.DisplayTrajectories = false; return; } if (Settings.fetch.DisplayTrajectories) { Settings.fetch.DisplayCompleteTrajectory = GUILayout.Toggle(Settings.fetch.DisplayCompleteTrajectory, "complete", GUILayout.Width(70)); } GUILayout.EndHorizontal(); Settings.fetch.BodyFixedMode = GUILayout.Toggle(Settings.fetch.BodyFixedMode, "Body-fixed mode"); GUILayout.Label("Max G-force: " + (traj.MaxAccel / 9.81).ToString("0.00")); if (lastPatch != null && lastPatch.impactPosition.HasValue) { Vector3 up = lastPatch.impactPosition.Value.normalized; Vector3 vel = lastPatch.impactVelocity - lastPatch.startingState.referenceBody.getRFrmVel(lastPatch.impactPosition.Value + lastPatch.startingState.referenceBody.position); float vVelMag = Vector3.Dot(vel, up); Vector3 vVel = up * vVelMag; float hVelMag = (vel - vVel).magnitude; GUILayout.Label("Impact: V = " + vVelMag.ToString("0.0") + "m/s, H = " + hVelMag.ToString("0.0") + "m/s"); } else { GUILayout.Label("Impact velocity: -"); } GUILayout.Space(10); if (Settings.fetch.DisplayTargetGUI = ToggleGroup(Settings.fetch.DisplayTargetGUI, "Target")) { GUI.enabled = traj.targetPosition.HasValue; if (GUILayout.Button("Unset target")) { Trajectory.SetTarget(); } GUI.enabled = true; GUILayout.BeginHorizontal(); var patch = traj.patches.LastOrDefault(); GUI.enabled = (patch != null && patch.impactPosition.HasValue); if (GUILayout.Button("Set current impact", GUILayout.Width(150))) { Trajectory.SetTarget(patch.startingState.referenceBody, patch.impactPosition); } GUI.enabled = true; if (GUILayout.Button("Set KSC", GUILayout.Width(70))) { var body = FlightGlobals.Bodies.SingleOrDefault(b => b.isHomeWorld); if (body != null) { Vector3d worldPos = body.GetWorldSurfacePosition(-0.04860002, -74.72425635, 2.0); Trajectory.SetTarget(body, worldPos - body.position); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); coords = GUILayout.TextField(coords, GUILayout.Width(170)); if (GUILayout.Button(new GUIContent("Set", "Enter target latitude and longitude, separated by a comma"), GUILayout.Width(50))) { string[] latLng = coords.Split(new char[] { ',', ';' }); var body = FlightGlobals.currentMainBody; if (latLng.Length == 2 && body != null) { double lat, lng; if (Double.TryParse(latLng[0].Trim(), out lat) && Double.TryParse(latLng[1].Trim(), out lng)) { Vector3d worldPos = body.GetWorldSurfacePosition(lat, lng, 2.0); Trajectory.SetTarget(body, worldPos - body.position); } } } GUILayout.EndHorizontal(); } GUILayout.Space(10); GUILayout.BeginHorizontal(); bool descentProfileGroup = Settings.fetch.DisplayDescentProfileGUI = ToggleGroup(Settings.fetch.DisplayDescentProfileGUI, "Descent profile", 120); DescentProfile.fetch.DoQuickControlsGUI(); GUILayout.EndHorizontal(); if (descentProfileGroup) { DescentProfile.fetch.DoGUI(); } GUILayout.Space(10); if (Settings.fetch.DisplaySettingsGUI = ToggleGroup(Settings.fetch.DisplaySettingsGUI, "Settings")) { GUILayout.BeginHorizontal(); GUILayout.Label("Max patches", GUILayout.Width(100)); Settings.fetch.MaxPatchCount = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)Settings.fetch.MaxPatchCount, 3, 10, GUILayout.Width(100))); GUILayout.Label(Settings.fetch.MaxPatchCount.ToString(), GUILayout.Width(15)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Max frames per patch", GUILayout.Width(100)); Settings.fetch.MaxFramesPerPatch = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)Settings.fetch.MaxFramesPerPatch, 1, 50, GUILayout.Width(100))); GUILayout.Label(Settings.fetch.MaxFramesPerPatch.ToString(), GUILayout.Width(15)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); Settings.fetch.AutoUpdateAerodynamicModel = GUILayout.Toggle(Settings.fetch.AutoUpdateAerodynamicModel, new GUIContent("Auto update", "Auto-update of the aerodynamic model. For example if a part is decoupled, the model needs to be updated. This is independent from trajectory update.")); if (GUILayout.Button("Update now")) { traj.InvalidateAerodynamicModel(); } GUILayout.EndHorizontal(); if (ToolbarManager.ToolbarAvailable) { Settings.fetch.UseBlizzyToolbar = GUILayout.Toggle(Settings.fetch.UseBlizzyToolbar, new GUIContent("Use Blizzy's toolbar", "Will take effect after restart")); } //Settings.fetch.AutoPilotAvailable = GUILayout.Toggle(Settings.fetch.AutoPilotAvailable, new GUIContent("Unlock auto-pilot (EXPERIMENTAL)", "Enables the auto-pilot interface. This is experimental, subject to change, and might crash your spaceplanes more often than not.")); Settings.fetch.AutoPilotAvailable = false; // auto-pilot disabled because it's incompatible with Remote Tech in its current implementation (and has some other bugs anyway) if (FlightGlobals.ActiveVessel != null) { GUILayout.Label("Position:"); GUILayout.BeginHorizontal(); var body = FlightGlobals.ActiveVessel.mainBody; var worldPos = FlightGlobals.ActiveVessel.GetWorldPos3D(); GUILayout.Label("lat=" + body.GetLatitude(worldPos).ToString("000.000000"), GUILayout.Width(110)); GUILayout.Label("lng=" + body.GetLongitude(worldPos).ToString("000.000000"), GUILayout.Width(110)); GUILayout.EndHorizontal(); } GUILayout.Label("Aerodynamic model: " + VesselAerodynamicModel.AerodynamicModelName); GUILayout.BeginHorizontal(); GUILayout.Label("Perf: " + (traj.ComputationTime * 1000.0f).ToString("0.0") + "ms (" + (traj.ComputationTime / traj.GameFrameTime * 100.0f).ToString("0") + "%)", GUILayout.Width(120)); GUILayout.Label(traj.ErrorCount + " error(s)", GUILayout.Width(80)); GUILayout.EndHorizontal(); } tooltip = GUI.tooltip; GUI.DragWindow(); }
public override void OnFixedUpdate() { if (myAttachedEngine.isOperational && myAttachedEngine.currentThrottle > 0 && myAttachedReactor != null) { if (!myAttachedReactor.isActive()) { myAttachedReactor.enableIfPossible(); } updateIspEngineParams(); float curve_eval_point = (float)Math.Min(FlightGlobals.getStaticPressure(vessel.transform.position), 1.0); float currentIsp = myAttachedEngine.atmosphereCurve.Evaluate(curve_eval_point); double ispratio = currentIsp / maxISP; this.current_isp = currentIsp; // scale down thrust if it's attached to the wrong sized reactor float heat_exchanger_thrust_divisor = 1; if (radius > myAttachedReactor.getRadius()) { heat_exchanger_thrust_divisor = myAttachedReactor.getRadius() * myAttachedReactor.getRadius() / radius / radius; } else { heat_exchanger_thrust_divisor = radius * radius / myAttachedReactor.getRadius() / myAttachedReactor.getRadius(); } if (myAttachedReactor.getRadius() == 0 || radius == 0) { heat_exchanger_thrust_divisor = 1; } // get the flameout safety limit atmospheric_limit = getAtmosphericLimit(); double thrust_limit = myAttachedEngine.thrustPercentage / 100; if (currentpropellant_is_jet) { int pre_coolers_active = vessel.FindPartModulesImplementing <FNModulePreecooler>().Where(prc => prc.isFunctional()).Count(); int intakes_open = vessel.FindPartModulesImplementing <ModuleResourceIntake>().Where(mre => mre.intakeEnabled).Count(); double proportion = Math.Pow((double)(intakes_open - pre_coolers_active) / (double)intakes_open, 0.1); if (double.IsNaN(proportion) || double.IsInfinity(proportion)) { proportion = 1; } part.temperature = (float)Math.Max((Math.Sqrt(vessel.srf_velocity.magnitude) * 20.0 / GameConstants.atmospheric_non_precooled_limit) * part.maxTemp * proportion, 1); } double thermal_power_received = consumeFNResource(assThermalPower * TimeWarp.fixedDeltaTime * myAttachedEngine.currentThrottle, FNResourceManager.FNRESOURCE_THERMALPOWER) / TimeWarp.fixedDeltaTime; consumeFNResource(thermal_power_received * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT); float power_ratio = 0.0f; double engineMaxThrust = 0.01; if (assThermalPower > 0) { power_ratio = (float)(thermal_power_received / assThermalPower); engineMaxThrust = Math.Max(thrust_limit * 2000.0 * thermal_power_received / maxISP / g0 * heat_exchanger_thrust_divisor * ispratio / myAttachedEngine.currentThrottle, 0.01); } //print ("B: " + engineMaxThrust); // set up TWR limiter if on //double additional_thrust_compensator = myAttachedEngine.finalThrust / (myAttachedEngine.maxThrust * myAttachedEngine.currentThrottle); double engine_thrust = engineMaxThrust; // engine thrust fixed //print ("A: " + engine_thrust*myAttachedEngine.velocityCurve.Evaluate((float)vessel.srf_velocity.magnitude)); if (!double.IsInfinity(engine_thrust) && !double.IsNaN(engine_thrust)) { if (isLFO) { myAttachedEngine.maxThrust = (float)(2.0 * engine_thrust); } else { myAttachedEngine.maxThrust = (float)engine_thrust; } } else { myAttachedEngine.maxThrust = 0.000001f; } // amount of fuel being used at max throttle with no atmospheric limits if (current_isp > 0) { double vcurve_at_current_velocity = 1; if (myAttachedEngine.useVelocityCurve) { vcurve_at_current_velocity = myAttachedEngine.velocityCurve.Evaluate((float)vessel.srf_velocity.magnitude); } fuel_flow_rate = engine_thrust / current_isp / g0 / 0.005 * TimeWarp.fixedDeltaTime; if (vcurve_at_current_velocity > 0) { fuel_flow_rate = fuel_flow_rate / vcurve_at_current_velocity; } } } else { if (myAttachedEngine.realIsp > 0) { atmospheric_limit = getAtmosphericLimit(); double vcurve_at_current_velocity = 1; if (myAttachedEngine.useVelocityCurve) { vcurve_at_current_velocity = myAttachedEngine.velocityCurve.Evaluate((float)vessel.srf_velocity.magnitude); } fuel_flow_rate = myAttachedEngine.maxThrust / myAttachedEngine.realIsp / g0 / 0.005 * TimeWarp.fixedDeltaTime / vcurve_at_current_velocity; } else { fuel_flow_rate = 0; } if (currentpropellant_is_jet) { part.temperature = 1; } if (myAttachedReactor == null && myAttachedEngine.isOperational && myAttachedEngine.currentThrottle > 0) { myAttachedEngine.Events ["Shutdown"].Invoke(); ScreenMessages.PostScreenMessage("Engine Shutdown: No reactor attached!", 5.0f, ScreenMessageStyle.UPPER_CENTER); } } //tell static helper methods we are currently updating things static_updating = true; static_updating2 = true; }
private void MainWindow(int id) { Trajectory traj = Trajectory.fetch; GUILayout.BeginHorizontal(); Settings.fetch.DisplayTrajectories = GUILayout.Toggle(Settings.fetch.DisplayTrajectories, "Show trajectory", GUILayout.Width(125)); Settings.fetch.DisplayTrajectoriesInFlight = GUILayout.Toggle(Settings.fetch.DisplayTrajectoriesInFlight, "In-Flight"); // check that we have patched conics. If not, apologize to the user and return. if (Settings.fetch.DisplayTrajectories && !Util.IsPatchedConicsAvailable) { ScreenMessages.PostScreenMessage( "Can't show trajectory because patched conics are not available." + " Please update your tracking station facility."); Settings.fetch.DisplayTrajectories = false; return; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); Settings.fetch.BodyFixedMode = GUILayout.Toggle(Settings.fetch.BodyFixedMode, "Body-fixed mode"); if (Settings.fetch.DisplayTrajectories) { Settings.fetch.DisplayCompleteTrajectory = GUILayout.Toggle(Settings.fetch.DisplayCompleteTrajectory, "complete", GUILayout.Width(70)); } GUILayout.EndHorizontal(); GUILayout.Label("Max G-force: " + guistring_gForce); GUILayout.Label(guistring_impactVelocity); GUILayout.Space(10); if (Settings.fetch.DisplayTargetGUI = ToggleGroup(Settings.fetch.DisplayTargetGUI, "Target")) { GUI.enabled = Trajectory.Target.WorldPosition.HasValue; GUILayout.Label(guistring_targetDistance); if (GUILayout.Button("Unset target")) { Trajectory.Target.Set(); } GUI.enabled = true; GUILayout.BeginHorizontal(); var patch = traj.Patches.LastOrDefault(); GUI.enabled = (patch != null && patch.ImpactPosition.HasValue); if (GUILayout.Button("Set current impact", GUILayout.Width(150))) { Trajectory.Target.Set(patch.StartingState.ReferenceBody, patch.ImpactPosition); } GUI.enabled = true; if (GUILayout.Button("Set KSC", GUILayout.Width(70))) { var body = FlightGlobals.Bodies.SingleOrDefault(b => b.isHomeWorld); if (body != null) { Vector3d worldPos = body.GetWorldSurfacePosition(-0.04860002, -74.72425635, 2.0); Trajectory.Target.Set(body, worldPos - body.position); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); Vessel targetVessel = FlightGlobals.fetch.VesselTarget?.GetVessel(); GUI.enabled = (patch != null && targetVessel != null && targetVessel.Landed // && targetVessel.lastBody == patch.startingState.referenceBody ); if (GUILayout.Button("Target vessel")) { Trajectory.Target.Set(targetVessel.lastBody, targetVessel.GetWorldPos3D() - targetVessel.lastBody.position); ScreenMessages.PostScreenMessage("Targeting vessel " + targetVessel.GetName()); } FinePrint.Waypoint navigationWaypoint = FlightGlobals.ActiveVessel?.navigationWaypoint; GUI.enabled = (navigationWaypoint != null); if (GUILayout.Button("Active waypoint")) { Trajectory.Target.Set(navigationWaypoint.celestialBody, navigationWaypoint.celestialBody.GetRelSurfacePosition(navigationWaypoint.latitude, navigationWaypoint.longitude, navigationWaypoint.altitude)); ScreenMessages.PostScreenMessage("Targeting waypoint " + navigationWaypoint.name); } GUILayout.EndHorizontal(); GUI.enabled = true; GUILayout.BeginHorizontal(); coords = GUILayout.TextField(Trajectory.Target.ManualText, GUILayout.Width(170)); if (coords != Trajectory.Target.ManualText) { Trajectory.Target.ManualText = coords; Trajectory.Target.Save(); } if (GUILayout.Button(new GUIContent("Set", "Enter target latitude and longitude, separated by a comma, in decimal format (with a dot for decimal separator)"), GUILayout.Width(50))) { string[] latLng = coords.Split(new char[] { ',', ';' }); var body = FlightGlobals.currentMainBody; if (latLng.Length == 2 && body != null) { double lat; double lng; if (double.TryParse(latLng[0].Trim(), out lat) && double.TryParse(latLng[1].Trim(), out lng)) { Vector3d relPos = body.GetWorldSurfacePosition(lat, lng, 2.0) - body.position; double altitude = Trajectory.GetGroundAltitude(body, relPos) + body.Radius; Trajectory.Target.Set(body, relPos * (altitude / relPos.magnitude)); } } } GUILayout.EndHorizontal(); } GUILayout.Space(10); GUILayout.BeginHorizontal(); bool descentProfileGroup = Settings.fetch.DisplayDescentProfileGUI = ToggleGroup(Settings.fetch.DisplayDescentProfileGUI, "Descent profile", 120); DescentProfile.fetch.DoQuickControlsGUI(); GUILayout.EndHorizontal(); if (descentProfileGroup) { DescentProfile.fetch.DoGUI(); } GUILayout.Space(10); if (Settings.fetch.DisplaySettingsGUI = ToggleGroup(Settings.fetch.DisplaySettingsGUI, "Settings")) { GUILayout.BeginHorizontal(); GUILayout.Label("Max patches", GUILayout.Width(100)); Settings.fetch.MaxPatchCount = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)Settings.fetch.MaxPatchCount, 3, 10, GUILayout.Width(100))); GUILayout.Label(Settings.fetch.MaxPatchCount.ToString(), GUILayout.Width(15)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Max frames per patch", GUILayout.Width(100)); Settings.fetch.MaxFramesPerPatch = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)Settings.fetch.MaxFramesPerPatch, 1, 50, GUILayout.Width(100))); GUILayout.Label(Settings.fetch.MaxFramesPerPatch.ToString(), GUILayout.Width(15)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); Settings.fetch.UseCache = GUILayout.Toggle(Settings.fetch.UseCache, new GUIContent("Use Cache", "Toggle cache usage. Trajectory will be more precise when cache disabled, but computation time will be higher. It's not recommended to keep it unchecked, unless your CPU can handle the load."), GUILayout.Width(80)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); Settings.fetch.AutoUpdateAerodynamicModel = GUILayout.Toggle(Settings.fetch.AutoUpdateAerodynamicModel, new GUIContent("Auto update", "Auto-update of the aerodynamic model. For example if a part is decoupled, the model needs to be updated. This is independent from trajectory update.")); if (GUILayout.Button("Update now")) { traj.InvalidateAerodynamicModel(); } GUILayout.EndHorizontal(); if (ToolbarManager.ToolbarAvailable) { Settings.fetch.UseBlizzyToolbar = GUILayout.Toggle(Settings.fetch.UseBlizzyToolbar, new GUIContent("Use Blizzy's toolbar", "Will take effect after restart")); } if (FlightGlobals.ActiveVessel != null) { GUILayout.Label("Position:"); GUILayout.BeginHorizontal(); GUILayout.Label("lat=" + guistring_Latitude, GUILayout.Width(110)); GUILayout.Label("lng=" + guistring_Longitude, GUILayout.Width(110)); GUILayout.EndHorizontal(); } GUILayout.Label("Aerodynamic model: " + traj.AerodynamicModelName); GUILayout.BeginHorizontal(); GUILayout.Label(String.Format("Perf: {0,5:F1}ms ({1,4:F1})%", traj.ComputationTime * 1000.0f, traj.ComputationTime / traj.GameFrameTime * 100.0f ), GUILayout.Width(130)); GUILayout.Label(traj.ErrorCount + " error(s)", GUILayout.Width(80)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Toggle(Settings.fetch.NewGui, new GUIContent("New Gui", "Swap to the New Gui"))) { Settings.fetch.NewGui = true; Settings.fetch.MainGUIEnabled = true; Settings.fetch.GUIEnabled = false; InputLockManager.RemoveControlLock("TrajectoriesFlightLock"); clickThroughLocked = false; } else { Settings.fetch.NewGui = false; Settings.fetch.MainGUIEnabled = false; Settings.fetch.GUIEnabled = true; } GUILayout.EndHorizontal(); } tooltip = GUI.tooltip; GUI.DragWindow(); }
public override void OnFixedUpdate() { base.OnFixedUpdate(); if (IsEnabled && myAttachedReactor != null && FNRadiator.hasRadiatorsForVessel(vessel)) { updateGeneratorPower(); // check if MaxStableMegaWattPower is changed var maxStableMegaWattPower = MaxStableMegaWattPower; if (maxStableMegaWattPower != _previousMaxStableMegaWattPower) { _powerState = PowerStates.powerChange; } _previousMaxStableMegaWattPower = maxStableMegaWattPower; if (maxStableMegaWattPower > 0 && (TimeWarp.fixedDeltaTime != previousTimeWarp || _powerState != PowerStates.powerOnline)) { _powerState = PowerStates.powerOnline; var powerBufferingBonus = myAttachedReactor.PowerBufferBonus * maxStableMegaWattPower; var requiredMegawattCapacity = Math.Max(0.0001, TimeWarp.fixedDeltaTime * maxStableMegaWattPower + powerBufferingBonus); var previousMegawattCapacity = Math.Max(0.0001, previousTimeWarp * maxStableMegaWattPower + powerBufferingBonus); if (megajouleResource != null) { megajouleResource.maxAmount = requiredMegawattCapacity; if (maxStableMegaWattPower > 0.1) { megajouleResource.amount = requiredMegawattCapacity > previousMegawattCapacity ? Math.Max(0, Math.Min(requiredMegawattCapacity, megajouleResource.amount + requiredMegawattCapacity - previousMegawattCapacity)) : Math.Max(0, Math.Min(requiredMegawattCapacity, (megajouleResource.amount / megajouleResource.maxAmount) * requiredMegawattCapacity)); } } //PartResource wasteheatResource = part.Resources.list.FirstOrDefault(r => r.resourceName == FNResourceManager.FNRESOURCE_WASTEHEAT); //if (wasteheatResource != null) //{ // var previousMaxAmount = wasteheatResource.maxAmount; // wasteheatResource.maxAmount = TimeWarp.fixedDeltaTime * part.mass * 1000; // this.part.RequestResource(FNResourceManager.FNRESOURCE_WASTEHEAT, previousTimeWarp > TimeWarp.fixedDeltaTime ? previousMaxAmount - wasteheatResource.maxAmount : 0); //} PartResource electricChargeResource = part.Resources.list.FirstOrDefault(r => r.resourceName == "ElectricCharge"); if (electricChargeResource != null) { //if (maxStableMegaWattPower <= 0) electricChargeResource.maxAmount = requiredMegawattCapacity; electricChargeResource.amount = maxStableMegaWattPower <= 0 ? 0 : Math.Min(electricChargeResource.maxAmount, electricChargeResource.amount); } } previousTimeWarp = TimeWarp.fixedDeltaTime; // don't produce any power when our reactor has stopped if (maxStableMegaWattPower <= 0) { PowerDown(); return; } else { powerDownFraction = 1; } double electrical_power_currently_needed; if (myAttachedReactor.ShouldApplyBalance(chargedParticleMode ? ElectricGeneratorType.charged_particle : ElectricGeneratorType.thermal)) { var chargedPowerPerformance = myAttachedReactor.EfficencyConnectedChargedEnergyGenrator * myAttachedReactor.ChargedPowerRatio; var thermalPowerPerformance = myAttachedReactor.EfficencyConnectedThermalEnergyGenrator * (1 - myAttachedReactor.ChargedPowerRatio); var totalPerformance = chargedPowerPerformance + thermalPowerPerformance; var balancePerformanceRatio = (chargedParticleMode ? chargedPowerPerformance / totalPerformance : thermalPowerPerformance / totalPerformance); electrical_power_currently_needed = (getCurrentUnfilledResourceDemand(FNResourceManager.FNRESOURCE_MEGAJOULES) + getSpareResourceCapacity(FNResourceManager.FNRESOURCE_MEGAJOULES)) * balancePerformanceRatio; } else { electrical_power_currently_needed = getCurrentUnfilledResourceDemand(FNResourceManager.FNRESOURCE_MEGAJOULES) + getSpareResourceCapacity(FNResourceManager.FNRESOURCE_MEGAJOULES); } double electricdt = 0; double electricdtps = 0; double max_electricdtps = 0; if (!chargedParticleMode) // thermal mode { double carnotEff = 1.0 - coldBathTemp / hotBathTemp; _totalEff = carnotEff * pCarnotEff * myAttachedReactor.ThermalEnergyEfficiency; myAttachedReactor.NotifyActiveThermalEnergyGenrator(_totalEff, ElectricGeneratorType.thermal); if (_totalEff <= 0 || coldBathTemp <= 0 || hotBathTemp <= 0 || maxThermalPower <= 0) { return; } double thermal_power_currently_needed = electrical_power_currently_needed / _totalEff; // _totalEff; double thermal_power_requested = Math.Max(Math.Min(maxThermalPower, thermal_power_currently_needed) * TimeWarp.fixedDeltaTime, 0.0); requestedPower_f = (float)thermal_power_requested / TimeWarp.fixedDeltaTime; double input_power = consumeFNResource(thermal_power_requested, FNResourceManager.FNRESOURCE_THERMALPOWER); if (!(myAttachedReactor.EfficencyConnectedChargedEnergyGenrator > 0) && input_power < thermal_power_requested) { input_power += consumeFNResource(thermal_power_requested - input_power, FNResourceManager.FNRESOURCE_CHARGED_PARTICLES); } double wastedt = input_power * _totalEff; consumeFNResource(wastedt, FNResourceManager.FNRESOURCE_WASTEHEAT); electricdt = input_power * _totalEff; electricdtps = Math.Max(electricdt / TimeWarp.fixedDeltaTime, 0.0); max_electricdtps = maxThermalPower * _totalEff; } else // charged particle mode { _totalEff = isupgraded ? upgradedDirectConversionEff : directConversionEff; myAttachedReactor.NotifyActiveChargedEnergyGenrator(_totalEff, ElectricGeneratorType.charged_particle); if (_totalEff <= 0) { return; } double charged_power_currently_needed = electrical_power_currently_needed; // _totalEff / ; var charged_power_requested = Math.Max(Math.Min(maxChargedPower, charged_power_currently_needed) * TimeWarp.fixedDeltaTime, 0.0); requestedPower_f = (float)charged_power_requested / TimeWarp.fixedDeltaTime; double input_power = consumeFNResource(charged_power_requested, FNResourceManager.FNRESOURCE_CHARGED_PARTICLES); electricdt = input_power * _totalEff; electricdtps = Math.Max(electricdt / TimeWarp.fixedDeltaTime, 0.0); double wastedt = input_power * _totalEff; max_electricdtps = maxChargedPower * _totalEff; consumeFNResource(wastedt, FNResourceManager.FNRESOURCE_WASTEHEAT); } outputPower = -(float)supplyFNResourceFixedMax(electricdtps * TimeWarp.fixedDeltaTime, max_electricdtps * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime; } else { previousTimeWarp = TimeWarp.fixedDeltaTime; if (IsEnabled && !vessel.packed) { if (!FNRadiator.hasRadiatorsForVessel(vessel)) { IsEnabled = false; Debug.Log("[WarpPlugin] Generator Shutdown: No radiators available!"); ScreenMessages.PostScreenMessage("Generator Shutdown: No radiators available!", 5.0f, ScreenMessageStyle.UPPER_CENTER); PowerDown(); } if (myAttachedReactor == null) { IsEnabled = false; Debug.Log("[WarpPlugin] Generator Shutdown: No reactor available!"); ScreenMessages.PostScreenMessage("Generator Shutdown: No reactor available!", 5.0f, ScreenMessageStyle.UPPER_CENTER); PowerDown(); } } else { PowerDown(); } } }
private void GenerateTrustFromReactorHeat() { if (!myAttachedReactor.IsActive) { myAttachedReactor.enableIfPossible(); } // determine ISP if (currentpropellant_is_jet) { updateIspEngineParams(); this.current_isp = myAttachedEngine.atmosphereCurve.Evaluate((float)Math.Min(FlightGlobals.getStaticPressure(vessel.transform.position), 1.0)); } else { maxISP = (float)(Math.Sqrt((double)myAttachedReactor.CoreTemperature) * (PluginHelper.IspCoreTempMult + IspTempMultOffset) * GetIspPropellantModifier()); assThermalPower = myAttachedReactor is InterstellarFusionReactor ? myAttachedReactor.MaximumPower * 0.95f : myAttachedReactor.MaximumPower; } // get the flameout safety limit if (currentpropellant_is_jet) { int pre_coolers_active = vessel.FindPartModulesImplementing <FNModulePreecooler>().Where(prc => prc.isFunctional()).Count(); int intakes_open = vessel.FindPartModulesImplementing <ModuleResourceIntake>().Where(mre => mre.intakeEnabled).Count(); double proportion = Math.Pow((double)(intakes_open - pre_coolers_active) / (double)intakes_open, 0.1); if (double.IsNaN(proportion) || double.IsInfinity(proportion)) { proportion = 1; } float temp = (float)Math.Max((Math.Sqrt(vessel.srf_velocity.magnitude) * 20.0 / GameConstants.atmospheric_non_precooled_limit) * part.maxTemp * proportion, 1); if (temp > part.maxTemp - 10.0f) { ScreenMessages.PostScreenMessage("Engine Shutdown: Catastrophic overheating was imminent!", 5.0f, ScreenMessageStyle.UPPER_CENTER); myAttachedEngine.Shutdown(); part.temperature = 1; } else { part.temperature = temp; } } double thermal_consume_total = assThermalPower * TimeWarp.fixedDeltaTime * myAttachedEngine.currentThrottle * GetAtmosphericLimit(); double thermal_power_received = consumeFNResource(thermal_consume_total, FNResourceManager.FNRESOURCE_THERMALPOWER) / TimeWarp.fixedDeltaTime; if (thermal_power_received * TimeWarp.fixedDeltaTime < thermal_consume_total) { thermal_power_received += consumeFNResource(thermal_consume_total - thermal_power_received * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_CHARGED_PARTICLES) / TimeWarp.fixedDeltaTime; } consumeFNResource(thermal_power_received * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT); // calculate max thrust double engineMaxThrust = 0.01; if (assThermalPower > 0) { double ispRatio = currentpropellant_is_jet ? this.current_isp / maxISP : 1; double thrust_limit = myAttachedEngine.thrustPercentage / 100.0; engineMaxThrust = Math.Max(thrust_limit * GetPowerTrustModifier() * GetHeatTrustModifier() * thermal_power_received / maxISP / PluginHelper.GravityConstant * heatExchangerThrustDivisor * ispRatio / myAttachedEngine.currentThrottle, 0.01); } double max_thrust_in_space = engineMaxThrust / myAttachedEngine.thrustPercentage * 100.0; double engine_thrust = max_thrust_in_space; // update engine thrust/ISP for thermal noozle if (!currentpropellant_is_jet) { pressureTreshold = exitArea * (float)GameConstants.EarthAthmospherePresureAtSeaLevel * (float)FlightGlobals.getStaticPressure(vessel.transform.position); engine_thrust = Math.Max(max_thrust_in_space - pressureTreshold, 0.00001); var thrustAtmosphereRatio = engine_thrust / Math.Max(max_thrust_in_space, 0.000001); var isp_reduction_fraction = thrustAtmosphereRatio * heatExchangerThrustDivisor; updateIspEngineParams(isp_reduction_fraction, max_thrust_in_space); this.current_isp = maxISP * isp_reduction_fraction; } if (!double.IsInfinity(engine_thrust) && !double.IsNaN(engine_thrust)) { myAttachedEngine.maxThrust = thrustPropellantMultiplier == 1f ? (float)engine_thrust : (float)(engine_thrust * thrustPropellantMultiplier); } else { myAttachedEngine.maxThrust = 0.000001f; } // amount of fuel being used at max throttle with no atmospheric limits if (current_isp > 0) { double vcurve_at_current_velocity = 1; if (myAttachedEngine.useVelocityCurve && myAttachedEngine.velocityCurve != null) { vcurve_at_current_velocity = myAttachedEngine.velocityCurve.Evaluate((float)vessel.srf_velocity.magnitude); } fuel_flow_rate = engine_thrust / current_isp / PluginHelper.GravityConstant / 0.005 * TimeWarp.fixedDeltaTime; if (vcurve_at_current_velocity > 0 && !double.IsInfinity(vcurve_at_current_velocity) && !double.IsNaN(vcurve_at_current_velocity)) { this.fuel_flow_rate = fuel_flow_rate / vcurve_at_current_velocity; } if (atmospheric_limit > 0 && !double.IsInfinity(atmospheric_limit) && !double.IsNaN(atmospheric_limit)) { this.fuel_flow_rate = fuel_flow_rate / atmospheric_limit; } } }
private void Update() { safeDisplay = display; if (workerEnabled) { while (craftAddQueue.Count > 0) { CraftChangeEntry cce = craftAddQueue.Dequeue(); AddCraftEntry(cce.playerName, cce.craftType, cce.craftName); } while (craftDeleteQueue.Count > 0) { CraftChangeEntry cce = craftDeleteQueue.Dequeue(); DeleteCraftEntry(cce.playerName, cce.craftType, cce.craftName); } while (craftResponseQueue.Count > 0) { CraftResponseEntry cre = craftResponseQueue.Dequeue(); SaveCraftFile(cre.craftType, cre.craftName, cre.craftData); } if (uploadCraftName != null) { UploadCraftFile(uploadCraftType, uploadCraftName); uploadCraftName = null; uploadCraftType = CraftType.VAB; } if (downloadCraftName != null) { DownloadCraftFile(selectedPlayer, downloadCraftType, downloadCraftName); downloadCraftName = null; downloadCraftType = CraftType.VAB; } if (deleteCraftName != null) { DeleteCraftEntry(Settings.fetch.playerName, deleteCraftType, deleteCraftName); using (MessageWriter mw = new MessageWriter()) { mw.Write <int>((int)CraftMessageType.DELETE_FILE); mw.Write <string>(Settings.fetch.playerName); mw.Write <int>((int)deleteCraftType); mw.Write <string>(deleteCraftName); NetworkWorker.fetch.SendCraftLibraryMessage(mw.GetMessageBytes()); } deleteCraftName = null; deleteCraftType = CraftType.VAB; } if (displayCraftUploadingMessage && ((UnityEngine.Time.realtimeSinceStartup - lastCraftMessageCheck) > CRAFT_MESSAGE_CHECK_INTERVAL)) { lastCraftMessageCheck = UnityEngine.Time.realtimeSinceStartup; if (craftUploadMessage != null) { craftUploadMessage.duration = 0f; } if (finishedUploadingCraft) { displayCraftUploadingMessage = false; craftUploadMessage = ScreenMessages.PostScreenMessage("Craft uploaded!", 2f, ScreenMessageStyle.UPPER_CENTER); } else { craftUploadMessage = ScreenMessages.PostScreenMessage("Uploading craft...", 1f, ScreenMessageStyle.UPPER_CENTER); } } } }
public void onVesselAboutToBeDestroyed(EventReport report) { Debug.Log("[KSPI] - Handling Impactor"); ConfigNode config; ConfigNode science_node; Vessel vessel = report.origin.vessel; float vesselMass; int science_experiment_number = 0; string vessel_impact_node_string = string.Concat("IMPACT_", vessel.id.ToString()); string vessel_seismic_node_string = string.Concat("SEISMIC_SCIENCE_", vessel.mainBody.name.ToUpper()); // Do nothing if we don't have a vessel. This seems improbable, but who knows. if (vessel == null) { Debug.Log("[KSPI] - Impactor: Ignored because the vessel is undefined."); return; } // Do nothing if we have recorded an impact less than 10 physics updates ago. This probably means this call // is a duplicate of a previous call. if (Planetarium.GetUniversalTime() - this.lastImpactTime < TimeWarp.fixedDeltaTime * 10f) { Debug.Log("[KSPI] - Impactor: Ignored because we've just recorded an impact."); return; } // Do nothing if we are a debris item less than ten physics-updates old. That probably means we were // generated by a recently-recorded impact. if (vessel.vesselType == VesselType.Debris && vessel.missionTime < Time.fixedDeltaTime * 10f) { Debug.Log("[KSPI] - Impactor: Ignored due to vessel being brand-new debris."); return; } vesselMass = vessel.GetTotalMass(); // Do nothing if we aren't very near the terrain. Note that using heightFromTerrain probably allows // impactors against the ocean floor... good luck. float vesselDimension = vessel.MOI.magnitude / vesselMass; if (vessel.heightFromSurface > Mathf.Max(vesselDimension, 0.75f)) { Debug.Log("[KSPI] - Impactor: Ignored due to vessel altitude being too high."); return; } // Do nothing if we aren't impacting the surface. if (!( report.other.ToLower().Contains(string.Intern("surface")) || report.other.ToLower().Contains(string.Intern("terrain")) || report.other.ToLower().Contains(vessel.mainBody.name.ToLower()) )) { Debug.Log("[KSPI] - Impactor: Ignored due to not impacting the surface."); return; } /* * NOTE: This is a deviation from current KSPI behavior. KSPI currently registers an impact over 40 m/s * regardless of its mass; this means that trivially light impactors (single instruments, even) could * trigger the experiment. * * The guard below requires that the impactor have at least as much vertical impact energy as a 1 Mg * object traveling at 40 m/s. This means that nearly-tangential impacts or very light impactors will need * to be much faster, but that heavier impactors may be slower. * * */ if ((Math.Pow(vessel.verticalSpeed, 2d) * vesselMass / 2d < 800d) && vessel.verticalSpeed > 20d) { Debug.Log("[KSPI] - Impactor: Ignored due to vessel imparting too little impact energy."); return; } config = PluginHelper.getPluginSaveFile(); if (config.HasNode(vessel_seismic_node_string)) { science_node = config.GetNode(vessel_seismic_node_string); science_experiment_number = science_node.nodes.Count; if (science_node.HasNode(vessel_impact_node_string)) { Debug.Log("[KSPI] - Impactor: Ignored because this vessel's impact has already been recorded."); return; } } else { science_node = config.AddNode(vessel_seismic_node_string); science_node.AddValue("name", "interstellarseismicarchive"); } int body = vessel.mainBody.flightGlobalsIndex; Vector3d net_vector = Vector3d.zero; bool first = true; double distribution_factor = 0; foreach (Vessel conf_vess in FlightGlobals.Vessels) { String vessel_probe_node_string = string.Concat("VESSEL_SEISMIC_PROBE_", conf_vess.id.ToString()); if (config.HasNode(vessel_probe_node_string)) { ConfigNode probe_node = config.GetNode(vessel_probe_node_string); // If the seismometer is inactive, skip it. bool is_active = false; if (probe_node.HasValue("is_active")) { bool.TryParse(probe_node.GetValue("is_active"), out is_active); if (!is_active) { continue; } } // If the seismometer is on another planet, skip it. int planet = -1; if (probe_node.HasValue("celestial_body")) { int.TryParse(probe_node.GetValue("celestial_body"), out planet); if (planet != body) { continue; } } // do sciency stuff Vector3d surface_vector = (conf_vess.transform.position - FlightGlobals.Bodies[body].transform.position); surface_vector = surface_vector.normalized; if (first) { first = false; net_vector = surface_vector; distribution_factor = 1; } else { distribution_factor += 1.0 - Vector3d.Dot(surface_vector, net_vector.normalized); net_vector = net_vector + surface_vector; } } } distribution_factor = Math.Min(distribution_factor, 3.5); // no more than 3.5x boost to science by using multiple detectors if (distribution_factor > 0 && !double.IsInfinity(distribution_factor) && !double.IsNaN(distribution_factor)) { ScreenMessages.PostScreenMessage("Impact Recorded, science report can now be accessed from one of your accelerometers deployed on this body.", 5f, ScreenMessageStyle.UPPER_CENTER); this.lastImpactTime = Planetarium.GetUniversalTime(); Debug.Log("[KSPI] - Impactor: Impact registered!"); ConfigNode impact_node = new ConfigNode(vessel_impact_node_string); impact_node.AddValue(string.Intern("transmitted"), bool.FalseString); impact_node.AddValue(string.Intern("vesselname"), vessel.vesselName); impact_node.AddValue(string.Intern("distribution_factor"), distribution_factor); science_node.AddNode(impact_node); config.Save(PluginHelper.PluginSaveFilePath); } }
private void DrawButtonsBlock(float widthOffset) { if (GUI.Button(new Rect(widthOffset, 36, ButtonSize, ButtonSize), "↻")) { //_camObject.transform.Rotate(new Vector3(0, 0, 180f)); _camObject.transform.Rotate(new Vector3(0, 0, 90f)); _isUpsideDown = !_isUpsideDown; _alignment++; if ((int)_alignment > 3) { _alignment = Alignment.up; } } if (GUI.RepeatButton(new Rect(widthOffset + ButtonSize, 36, ButtonSize, ButtonSize), "↑")) { switch (_alignment) { case Alignment.up: RotateY += _rotateStep; break; case Alignment.right: RotateZ -= _rotateStep; break; case Alignment.down: RotateY -= _rotateStep; break; case Alignment.left: RotateZ += _rotateStep; break; } } if (GUI.Button(new Rect(widthOffset + ButtonSize * 2, 36, ButtonSize, ButtonSize), "⦿")) { if (ThisPart.vessel.Equals(FlightGlobals.ActiveVessel)) { if (!TargetHelper.IsTargetSelect) { ScreenMessages.PostScreenMessage("NO TARGET FOR SCANNING", 3f, ScreenMessageStyle.UPPER_CENTER); } else { if (Hits <= 0) { ScreenMessages.PostScreenMessage("BULLETS DEPLETED", 3f, ScreenMessageStyle.UPPER_CENTER); } else { var id = PartResourceLibrary.Instance.GetDefinition(_resourceName).id; double amount; double maxAmount; ThisPart.GetConnectedResourceTotals(id, out amount, out maxAmount); if (amount > _resourceUsage) { ThisPart.RequestResource(id, (double)_resourceUsage); var hit = PartGameObject.GetChild($"{_bulletName}{Hits:000}"); Object.Destroy(hit); Hits--; _isRayEnabled = true; IsWaitForRay = true; _isScienceActivate = false; } else { ScreenMessages.PostScreenMessage("NOT ENOUGH ELECTRICITY FOR SCAN", 3f, ScreenMessageStyle.UPPER_CENTER); } } //if (HitCounter() && UseResourceForScanning()) //{ // _isRayEnabled = true; // IsWaitForRay = true; // _isScienceActivate = false; //} } } else { ScreenMessages.PostScreenMessage("Camera not on active vessel", 3f, ScreenMessageStyle.UPPER_CENTER); } } if (GUI.RepeatButton(new Rect(widthOffset, 36 + ButtonSize, ButtonSize, ButtonSize), "←")) { switch (_alignment) { case Alignment.up: RotateZ -= _rotateStep; break; case Alignment.right: RotateY -= _rotateStep; break; case Alignment.down: RotateZ += _rotateStep; break; case Alignment.left: RotateY += _rotateStep; break; } } if (GUI.Button(new Rect(widthOffset + ButtonSize, 36 + ButtonSize, ButtonSize, ButtonSize), "o")) { IsToZero = true; } if (GUI.RepeatButton(new Rect(widthOffset + ButtonSize * 2, 36 + ButtonSize, ButtonSize, ButtonSize), "→")) { #if false if (!_isUpsideDown) { RotateZ += _rotateStep; } else { RotateZ -= _rotateStep; } #endif switch (_alignment) { case Alignment.up: RotateZ += _rotateStep; break; case Alignment.right: RotateY += _rotateStep; break; case Alignment.down: RotateZ -= _rotateStep; break; case Alignment.left: RotateY -= _rotateStep; break; } } if (GUI.Button(new Rect(widthOffset, 36 + ButtonSize * 2, ButtonSize, ButtonSize), "-")) { CurrentZoom += 0.5f; if (CurrentZoom > MaxZoom) { CurrentZoom = MaxZoom; } } if (GUI.RepeatButton(new Rect(widthOffset + ButtonSize, 36 + ButtonSize * 2, ButtonSize, ButtonSize), "↓")) { #if false if (_rotateYbuffer > 0) { if (!_isUpsideDown) { RotateY -= _rotateStep; } else { RotateY += _rotateStep; } } #endif switch (_alignment) { case Alignment.up: RotateY -= _rotateStep; break; case Alignment.right: RotateZ += _rotateStep; break; case Alignment.down: RotateY += _rotateStep; break; case Alignment.left: RotateZ -= _rotateStep; break; } } if (GUI.Button(new Rect(widthOffset + ButtonSize * 2, 36 + ButtonSize * 2, ButtonSize, ButtonSize), "+")) { CurrentZoom -= 0.5f; if (CurrentZoom < MinZoom) { CurrentZoom = MinZoom; } } }
public override void OnStart(StartState state) { base.OnStart(state); if (state == StartState.Editor || state == StartState.None) { return; } //Loading texture texStrut = GameDatabase.Instance.GetTexture(tubeTexPath, false); if (!texStrut) { KAS_Shared.DebugError("tube texture loading error !"); ScreenMessages.PostScreenMessage( string.Format( "Texture file : {0} has not been found, please check your KAS installation !", tubeTexPath), 10, ScreenMessageStyle.UPPER_CENTER); } // loading sounds KAS_Shared.createFXSound(this.part, fxSndLink, sndLinkPath, false); KAS_Shared.createFXSound(this.part, fxSndUnlink, sndUnlinkPath, false); KAS_Shared.createFXSound(this.part, fxSndBroke, sndBrokePath, false); // loading strut renderer strutRenderer = this.part.gameObject.AddComponent <KAS_Tube>(); strutRenderer.tubeTexTilingOffset = textureTiling; strutRenderer.tubeScale = tubeScale; strutRenderer.sphereScale = jointScale; strutRenderer.tubeTexture = texStrut; strutRenderer.sphereTexture = texStrut; strutRenderer.tubeJoinedTexture = texStrut; strutRenderer.srcNode = strutTransform; // loading tube type switch (tubeSrcType) { case "None": strutRenderer.srcJointType = KAS_Tube.tubeJointType.None; break; case "Rounded": strutRenderer.srcJointType = KAS_Tube.tubeJointType.Rounded; break; case "ShiftedAndRounded": strutRenderer.srcJointType = KAS_Tube.tubeJointType.ShiftedAndRounded; break; case "Joined": strutRenderer.srcJointType = KAS_Tube.tubeJointType.Joined; break; default: strutRenderer.srcJointType = KAS_Tube.tubeJointType.Joined; break; } switch (tubeTgtType) { case "None": strutRenderer.tgtJointType = KAS_Tube.tubeJointType.None; break; case "Rounded": strutRenderer.tgtJointType = KAS_Tube.tubeJointType.Rounded; break; case "ShiftedAndRounded": strutRenderer.tgtJointType = KAS_Tube.tubeJointType.ShiftedAndRounded; break; case "Joined": strutRenderer.tgtJointType = KAS_Tube.tubeJointType.Joined; break; default: strutRenderer.tgtJointType = KAS_Tube.tubeJointType.Joined; break; } // Reset link if docked if (attachMode.Docked && !linked) { KAS_Shared.DebugLog("OnStart(strut) Docked strut detected from save, relinking..."); KASModuleStrut linkedStrutModuleSavedD = dockedAttachModule.GetComponent <KASModuleStrut>(); LinkTo(linkedStrutModuleSavedD, false, true); } // Loading onVesselWasModified KSP event GameEvents.onVesselWasModified.Add(new EventData <Vessel> .OnEvent(this.OnVesselWasModified)); }
private bool LinkTo(KASModuleStrut tgtModule, bool checkCondition = true, bool setJointOrDock = true) { //Check condition if needed if (checkCondition) { if (!CheckLink(this.strutTransform, tgtModule.strutTransform, true)) { ScreenMessages.PostScreenMessage("Max angle or length reached, cannot link!", 5, ScreenMessageStyle.UPPER_CENTER); return(false); } if (tgtModule == this) { ScreenMessages.PostScreenMessage( string.Format("{0} cannot be linked to itself!", part.partInfo.title), 5, ScreenMessageStyle.UPPER_CENTER); return(false); } if (tgtModule.type != this.type) { ScreenMessages.PostScreenMessage( string.Format("{0} cannot be linked to {1} because they are not compatible!", part.partInfo.title, tgtModule.part.partInfo.title), 5, ScreenMessageStyle.UPPER_CENTER); return(false); } if (tgtModule.vessel != vessel && !allowDock) { ScreenMessages.PostScreenMessage( string.Format("{0} cannot be linked to another vessel!", part.partInfo.title), 5, ScreenMessageStyle.UPPER_CENTER); return(false); } } // Load tube renderer in this module this.StopEvaLink(); this.strutRenderer.tgtNode = tgtModule.strutTransform; this.strutRenderer.shaderName = "Diffuse"; this.strutRenderer.color = Color.white; this.strutRenderer.color.a = 1f; this.strutRenderer.Load(); // Set references for the current module this.Events["ContextMenuUnlink"].guiActiveUnfocused = true; this.Events["ContextMenuLink"].guiActiveUnfocused = false; this.linkedStrutModule = tgtModule; this.linked = true; // Set references for the target module tgtModule.linkedStrutModule = this; tgtModule.Events["ContextMenuUnlink"].guiActiveUnfocused = true; tgtModule.Events["ContextMenuLink"].guiActiveUnfocused = false; tgtModule.linked = true; tgtStrutPartID = tgtModule.part.flightID.ToString(); tgtStrutVesselID = tgtModule.part.vessel.id.ToString(); KAS_Shared.InvalidateContextMenu(this.part); KAS_Shared.InvalidateContextMenu(tgtModule.part); if (setJointOrDock) { // Create joint or dock part if (tgtModule.vessel == vessel) { if (tgtModule.part.parent != part && part.parent != tgtModule.part) { KAS_Shared.DebugLog("LinkTo(Strut) Parts are from the same vessel but are not connected," + " setting joint..."); if (part.parent && tgtModule.part.parent) { KAS_Shared.DebugLog("LinkTo(Strut) Set joint on struts parents"); AttachFixed(part.parent, tgtModule.part.parent, breakForce); } else { KAS_Shared.DebugLog("LinkTo(Strut) Set joint on struts"); AttachFixed(part, tgtModule.part, breakForce); } } } else { KAS_Shared.DebugLog("LinkTo(Strut) Parts are from a different vessel, docking..."); AttachDocked(tgtModule); } } else { KAS_Shared.DebugLog("LinkTo(Strut) setJointOrDock = false, ignoring dock and creating joint"); } // Connect fuel flow when appropriate bool both_attached = this.part.srfAttachNode.attachedPart && tgtModule.part.srfAttachNode.attachedPart; this.Events["ContextMenuTogglePump"].active = this.allowPumpFuel && both_attached; if (this.pumpFuel) { this.StartPump(checkCondition); } tgtModule.Events["ContextMenuTogglePump"].active = tgtModule.allowPumpFuel && both_attached; if (tgtModule.pumpFuel) { tgtModule.StartPump(checkCondition); } return(true); }
// Repair the reactor to max Repair percent public void DoReactorRepair() { this.CoreIntegrity = MaxRepairPercent; ScreenMessages.PostScreenMessage(new ScreenMessage(Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Message_Repair_RepairSuccess", MaxRepairPercent.ToString("F0")), 5.0f, ScreenMessageStyle.UPPER_CENTER)); }
//////////////////////////// private void ScreenMsg(string msg) { ScreenMessages.PostScreenMessage(new ScreenMessage(msg, 4, ScreenMessageStyle.UPPER_CENTER)); }
public void OnGUI() { if (siteLocations.Count < 1) { return; } if (Event.current.type == EventType.Repaint || Event.current.isMouse) { OnDraw(); } GUI.skin = HighLogic.Skin; if (bStyle == null) { bStyle = new GUIStyle(GUI.skin.button) { padding = new RectOffset(), contentOffset = new Vector2() }; } if (oldButton) { if (GUI.Button(new Rect(Screen.width - 100, 45, 100, 30), "Launch Sites")) { showWindow = !showWindow; } } else { if (GUI.Button(new Rect(Screen.width - 33, 45, 28, 28), (showWindow ? lsButtonHighlight : lsButtonNormal), bStyle)) { showWindow = !showWindow; } } if (GUI.Button(new Rect(Screen.width - 33, 78, 28, 28), (showSites ? eyeButtonHighlight : eyeButtonNormal), bStyle)) { showSites = !showSites; } if (showWindow) { if (oldButton) { GUILayout.BeginArea(new Rect(Screen.width - 333, 75, 300, 400)); } else { GUILayout.BeginArea(new Rect(Screen.width - 333, 45, 300, 400)); } scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Width(300), GUILayout.Height(400)); Color defColor = GUI.color; foreach (KeyValuePair <string, LaunchSite> kvp in siteLocations) { bool isActiveSite = kvp.Value.name.Equals(activeSite); GUILayout.BeginHorizontal(); if (GUILayout.Button(magButtonNormal, bStyle, GUILayout.MaxWidth(28))) { FocusOnSite(kvp.Value.geographicLocation); } if (isActiveSite) { GUI.contentColor = XKCDColors.ElectricLime; } if (GUILayout.Button(new GUIContent(kvp.Value.displayName, kvp.Value.description))) { if (isActiveSite) { ScreenMessages.PostScreenMessage("Cannot set launch site to active site.", 2.5f, ScreenMessageStyle.LOWER_CENTER); } else { SetSite(kvp.Value); } } GUI.contentColor = defColor; GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); GUILayout.EndArea(); GUI.backgroundColor = XKCDColors.AlmostBlack; if (curTooltip != "") { if (oldButton) { GUI.Label(new Rect(Screen.width - 633, 75, 300, 400), GUI.tooltip, infoLabel); } else { GUI.Label(new Rect(Screen.width - 633, 45, 300, 400), GUI.tooltip, infoLabel); } } if (Event.current.type == EventType.Repaint) { curTooltip = GUI.tooltip; } } }
// FixedUpdate is also called while not staged public void FixedUpdate() { var cryostat_resource = part.Resources[resourceName]; if (cryostat_resource == null || double.IsPositiveInfinity(currentPowerReq)) { boiloff = 0; return; } var fixedDeltaTime = (double)(decimal)Math.Round(TimeWarp.fixedDeltaTime, 7); if (!isDisabled && currentPowerReq > 0) { UpdateElectricChargeBuffer(Math.Max(currentPowerReq, 0.1 * powerReqKW)); var fixedPowerReqKW = currentPowerReq * fixedDeltaTime; var fixedRecievedChargeKW = CheatOptions.InfiniteElectricity ? fixedPowerReqKW : consumeFNResource(fixedPowerReqKW / 1000, ResourceManager.FNRESOURCE_MEGAJOULES) * 1000; if (fixedRecievedChargeKW <= fixedPowerReqKW) { fixedRecievedChargeKW += part.RequestResource(ResourceManager.FNRESOURCE_MEGAJOULES, (fixedPowerReqKW - fixedRecievedChargeKW) / 1000) * 1000; } if (currentPowerReq < 1000 && fixedRecievedChargeKW <= fixedPowerReqKW) { fixedRecievedChargeKW += part.RequestResource(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, fixedPowerReqKW - fixedRecievedChargeKW); } recievedPowerKW = fixedRecievedChargeKW / fixedDeltaTime; } else { recievedPowerKW = 0; } bool hasExtraBoiloff = initializationCountdown == 0 && powerReqKW > 0 && currentPowerReq > 0 && recievedPowerKW < currentPowerReq && previousRecievedPowerKW < previousPowerReq; var boiloffReducuction = !hasExtraBoiloff ? boilOffRate : boilOffRate + (boilOffAddition * (1 - recievedPowerKW / currentPowerReq)); boiloff = CheatOptions.IgnoreMaxTemperature || boiloffReducuction <= 0 ? 0 : boiloffReducuction * environmentBoiloff; if (boiloff > 0.0000000001) { var boilOffAmount = boiloff * fixedDeltaTime; cryostat_resource.amount = Math.Max(0, cryostat_resource.amount - boilOffAmount); boiloffStr = boiloff.ToString("0.0000000") + " L/s " + cryostat_resource.resourceName; if (hasExtraBoiloff && part.vessel.isActiveVessel && !warningShown) { warningShown = true; var message = "Warning: " + boiloffStr + " Boiloff"; Debug.LogWarning("[KSPI] - FNModuleCryostat: " + message); ScreenMessages.PostScreenMessage(message, 5, ScreenMessageStyle.UPPER_CENTER); } } else { warningShown = false; boiloffStr = "0.0000000 L/s " + cryostat_resource.resourceName; } previousPowerReq = currentPowerReq; previousRecievedPowerKW = recievedPowerKW; }
// Physics update public override void OnFixedUpdate() { if (FlightGlobals.fetch == null || !isEnabled) { return; } totalMassFlow = this.requestedMassFlow; // retreive ratios var propellant_ratio = hydrogenPropellant.ratio; var deuterium_ratio = deuteriumPropellant.ratio; var tritium_ratio = tritiumPropellant.ratio; var sumOfRatios = propellant_ratio + deuterium_ratio + tritium_ratio; // Resource demand float demandReqPropellant = ((propellant_ratio / sumOfRatios) * this.requestedMassFlow) / densityHydrogen; float demandReqDeuterium = ((deuterium_ratio / sumOfRatios) * this.requestedMassFlow) / densityDeuterium; float demandReqTritium = ((tritium_ratio / sumOfRatios) * this.requestedMassFlow) / densityTritium; // Realtime mode if (!this.vessel.packed) { // Resource demand propellantUsed = demandReqPropellant; deuteriumUsed = demandReqDeuterium; tritiumUsed = demandReqTritium; // if not transitioning from warp to real // Update values to use during timewarp if (!warpToReal) //&& vessel.ctrlState.mainThrottle == previousThrottle) { IspPersistent = realIsp; ThrottlePersistent = vessel.ctrlState.mainThrottle; this.CalculateThrust(); // verify we have thrust if ((vessel.ctrlState.mainThrottle > 0 && finalThrust > 0) || (vessel.ctrlState.mainThrottle == 0 && finalThrust == 0)) { ThrustPersistent = finalThrust; } } } else if (part.vessel.situation != Vessel.Situations.SUB_ORBITAL) { // Timewarp mode: perturb orbit using thrust warpToReal = true; // Set to true for transition to realtime double UT = Planetarium.GetUniversalTime(); // Universal time propellantUsed = (float)part.RequestResource(InterstellarResourcesConfiguration.Instance.Hydrogen, demandReqPropellant * TimeWarp.fixedDeltaTime) / TimeWarp.fixedDeltaTime; deuteriumUsed = (float)part.RequestResource(InterstellarResourcesConfiguration.Instance.Deuterium, demandReqDeuterium * TimeWarp.fixedDeltaTime) / TimeWarp.fixedDeltaTime; tritiumUsed = (float)part.RequestResource(InterstellarResourcesConfiguration.Instance.Tritium, demandReqTritium * TimeWarp.fixedDeltaTime) / TimeWarp.fixedDeltaTime; // Calculate thrust and deltaV if demand output > 0 if (propellantUsed > 0 && deuteriumUsed > 0 && tritiumUsed > 0) { double vesselMass = this.vessel.GetTotalMass(); // Current mass double m1 = vesselMass - (this.requestedMassFlow * TimeWarp.fixedDeltaTime); // Mass at end of burn if (m1 <= 0 || vesselMass <= 0) { return; } double deltaV = IspPersistent * PluginHelper.GravityConstant * Math.Log(vesselMass / m1); // Delta V from burn Vector3d thrustV = this.part.transform.up; // Thrust direction Vector3d deltaVV = deltaV * thrustV; // DeltaV vector vessel.orbit.Perturb(deltaVV, UT, TimeWarp.fixedDeltaTime); // Update vessel orbit } // Otherwise, if throttle is turned on, and demand out is 0, show warning else if (ThrottlePersistent > 0) { ScreenMessages.PostScreenMessage("Out of resource", 5.0f); } } else //if (vessel.ctrlState.mainThrottle > 0) { ScreenMessages.PostScreenMessage("Cannot accelerate and timewarp durring sub orbital spaceflight!", 5.0f, ScreenMessageStyle.UPPER_CENTER); } // Update display numbers thrust_d = ThrustPersistent; isp_d = IspPersistent; throttle_d = ThrottlePersistent; previousThrottle = vessel.ctrlState.mainThrottle; }
public override void PrintMissingResources() { ScreenMessages.PostScreenMessage(Localizer.Format("#LOC_KSPIE_HeavyWaterElectroliser_Postmsg") + " " + _waterHeavyResourceName, 3.0f, ScreenMessageStyle.UPPER_CENTER);//Missing }
private void InitiateWarp() { if (maximumWarpSpeedFactor < selected_factor) { selected_factor = minimumPowerAllowedFactor; } float new_warp_factor = engine_throtle[selected_factor]; currentPowerRequirementForWarp = GetPowerRequirementForWarp(new_warp_factor); float power_returned = CheatOptions.InfiniteElectricity ? currentPowerRequirementForWarp : consumeFNResource(currentPowerRequirementForWarp * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime; if (power_returned < 0.99 * currentPowerRequirementForWarp) { initiateWarpTimeout--; if (initiateWarpTimeout == 1) { while (selected_factor != minimum_selected_factor) { ReduceWarpPower(); new_warp_factor = engine_throtle[selected_factor]; currentPowerRequirementForWarp = GetPowerRequirementForWarp(new_warp_factor); if (power_returned >= currentPowerRequirementForWarp) { return; } } } if (initiateWarpTimeout == 0) { ScreenMessages.PostScreenMessage("Not enough power to initiate warp " + power_returned + " " + currentPowerRequirementForWarp, 5.0f, ScreenMessageStyle.UPPER_CENTER); IsCharging = true; return; } } initiateWarpTimeout = 0; // stop initiating to warp vesselWasInOuterspace = (this.vessel.altitude > this.vessel.mainBody.atmosphereDepth * 10); // consume all exotic matter to create warp field part.RequestResource(InterstellarResourcesConfiguration.Instance.ExoticMatter, exotic_power_required); warp_sound.Play(); warp_sound.loop = true; active_part_heading = new Vector3d(part.transform.up.x, part.transform.up.z, part.transform.up.y); heading_act = active_part_heading * GameConstants.warpspeed * new_warp_factor; serialisedwarpvector = ConfigNode.WriteVector(heading_act); vessel.GoOnRails(); vessel.orbit.UpdateFromStateVectors(vessel.orbit.pos, vessel.orbit.vel + heading_act, vessel.orbit.referenceBody, Planetarium.GetUniversalTime()); vessel.GoOffRails(); IsEnabled = true; existing_warpfactor = new_warp_factor; previous_Frame_heading = active_part_heading; }
private void scienceReceive(float sci, ScienceSubject sub, ProtoVessel pv, bool reverse) { if (this.Root.ContractState != Contract.State.Active) { return; } if (sub == null) { return; } if (type == 0 || type == 2) { if (!string.IsNullOrEmpty(biomeName)) { if (sub.id == subject) { if (HighLogic.LoadedScene == GameScenes.SPACECENTER || HighLogic.LoadedScene == GameScenes.TRACKSTATION) { base.SetComplete(); } else { returnedScience += sci; if (returnedScience >= scienceContainer.Exp.baseValue * scienceContainer.Transmit * sub.subjectValue * 0.3f) { ScreenMessages.PostScreenMessage("DMagic Orbital Science Survey Parameter Complete", 4f, ScreenMessageStyle.UPPER_CENTER); base.SetComplete(); } else { ScreenMessages.PostScreenMessage("This area has already been studied, try investigating another region to complete the contract", 6f, ScreenMessageStyle.UPPER_CENTER); } } } } else { if (sub.id.Contains(subject)) { if (HighLogic.LoadedScene == GameScenes.SPACECENTER || HighLogic.LoadedScene == GameScenes.TRACKSTATION) { base.SetComplete(); } else { returnedScience += sci; if (returnedScience >= scienceContainer.Exp.baseValue * scienceContainer.Transmit * sub.subjectValue * 0.3f) { ScreenMessages.PostScreenMessage("DMagic Orbital Science Survey Parameter Complete", 4f, ScreenMessageStyle.UPPER_CENTER); base.SetComplete(); } else { if (DMUtils.biomeRelevant(this.Situation, (int)this.Container.Exp.biomeMask)) { ScreenMessages.PostScreenMessage("This area has already been studied, try investigating another region to complete the contract", 6f, ScreenMessageStyle.UPPER_CENTER); } else { ScreenMessages.PostScreenMessage("Not enough science remaining; this experiment may need to be returned to Kerbin for credit", 6f, ScreenMessageStyle.UPPER_CENTER); } } } } } } else if (type == 1) { if (sub.id.Contains(subject)) { base.SetComplete(); } } }
public void UpdateWarpSpeed() { if (!IsEnabled || exotic_power_required <= 0) { return; } float new_warp_factor = engine_throtle[selected_factor]; currentPowerRequirementForWarp = GetPowerRequirementForWarp(new_warp_factor); float available_power = CheatOptions.InfiniteElectricity ? currentPowerRequirementForWarp : (float)getStableResourceSupply(FNResourceManager.FNRESOURCE_MEGAJOULES); float power_returned; if (CheatOptions.InfiniteElectricity) { power_returned = currentPowerRequirementForWarp; } else { power_returned = consumeFNResource(currentPowerRequirementForWarp * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime; if (!CheatOptions.IgnoreMaxTemperature) { supplyFNResource(-power_returned * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT); } } // retreive vessel heading Vector3d new_part_heading = new Vector3d(part.transform.up.x, part.transform.up.z, part.transform.up.y); // detect any changes in vessel heading and heading stability magnitudeDiff = (float)(active_part_heading - new_part_heading).magnitude; magnitudeChange = (float)(previous_Frame_heading - new_part_heading).magnitude; previous_Frame_heading = new_part_heading; // detect power shortage if (currentPowerRequirementForWarp > available_power) { insufficientPowerTimeout = -1; } else if (power_returned < 0.99 * currentPowerRequirementForWarp) { insufficientPowerTimeout--; } else { insufficientPowerTimeout = 10; } if (this.vessel.altitude < this.vessel.mainBody.atmosphereDepth * 2) { if (vesselWasInOuterspace) { DeactivateWarpDrive(); return; } } else { vesselWasInOuterspace = true; } // determine if we need to change speed and heading var hasPowerShortage = insufficientPowerTimeout < 0; var hasHeadingChanged = magnitudeDiff > 0.05 && magnitudeChange < 0.0001; var hasWarpFactorChange = existing_warpfactor != new_warp_factor; var hasGavityPullInbalance = maximumWarpSpeedFactor < selected_factor; if (hasGavityPullInbalance) { selected_factor = maximumWarpSpeedFactor; } if (!CheatOptions.InfiniteElectricity && hasPowerShortage) { if (selected_factor == minimumPowerAllowedFactor || selected_factor == minimum_selected_factor || power_returned < 0.99 * PowerRequirementForMaximumAllowedLightSpeed) { ScreenMessages.PostScreenMessage("Critical Power shortage, deactivating warp"); DeactivateWarpDrive(); return; } ScreenMessages.PostScreenMessage("Insufficient Power " + power_returned.ToString("0.0") + " / " + currentPowerRequirementForWarp.ToString("0.0") + ", reducing power drain"); ReduceWarpPower(); } if (hasWarpFactorChange || hasPowerShortage || hasHeadingChanged || hasGavityPullInbalance) { new_warp_factor = engine_throtle[selected_factor]; existing_warpfactor = new_warp_factor; Vector3d reverse_heading = new Vector3d(-heading_act.x, -heading_act.y, -heading_act.z); heading_act = new_part_heading * GameConstants.warpspeed * new_warp_factor; active_part_heading = new_part_heading; serialisedwarpvector = ConfigNode.WriteVector(heading_act); vessel.GoOnRails(); vessel.orbit.UpdateFromStateVectors(vessel.orbit.pos, vessel.orbit.vel + reverse_heading + heading_act, vessel.orbit.referenceBody, Planetarium.GetUniversalTime()); vessel.GoOffRails(); } }
private void DoSimulationNotification() { Log.Info("DoSimulationNotification simNotification: " + simNotification); ScreenMessages.PostScreenMessage(simNotification, 1.0f, ScreenMessageStyle.UPPER_CENTER); }
private void EaseLoadingForExtendedRange() { if (!_loading) { return; } if (!FlightGlobals.currentMainBody.pqsController.isBuildingMaps) { --_reset; } if (_reset > 0) { return; } _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); } ScreenMessages.PostScreenMessage( "[PhysicsRangeExtender]Extending terrain distance: entangling.", 3f, ScreenMessageStyle.UPPER_CENTER); Debug.LogError($"Black Spell entangling {_vesEnume.Current?.vesselName}"); break; case 2: ScreenMessages.PostScreenMessage( "[PhysicsRangeExtender]Extending terrain distance: condensing.", 3f, ScreenMessageStyle.UPPER_CENTER); ++_stage; break; case 3: ScreenMessages.PostScreenMessage( "[PhysicsRangeExtender]Extending terrain distance: releasing energies.", 3f, ScreenMessageStyle.UPPER_CENTER); _reset = 100; ++_stage; break; case 4: CheatOptions.NoCrashDamage = _crashDamage; CheatOptions.UnbreakableJoints = _joints; _loading = false; ScreenMessages.PostScreenMessage( "[PhysicsRangeExtender]Extending terrain distance: complete.", 3f, ScreenMessageStyle.UPPER_CENTER); break; } }
private void ApplyEVAEffect(LifeSupportStatus kStat, ProtoCrewMember crew, Vessel v, int effectId) { /* * SIDE EFFECTS: * * 0 = No Effect (The feature is effectively turned off * 1 = Grouchy (they become a Tourist until rescued) * 2 = Mutinous (A tourist, but destroys a part of a nearby vessel...) * 3 = Instantly 'wander' back to the KSC - don't ask us how! * 4 = M.I.A. (will eventually respawn) * 5 = K.I.A. * */ var msg = ""; switch (effectId) { case 1: //Grouchy if (crew.type != ProtoCrewMember.KerbalType.Tourist) { msg = string.Format("{0} refuses to work", crew.name); kStat.OldTrait = crew.experienceTrait.Title; crew.type = ProtoCrewMember.KerbalType.Tourist; KerbalRoster.SetExperienceTrait(crew, "Tourist"); kStat.IsGrouchy = true; LifeSupportManager.Instance.TrackKerbal(kStat); } break; case 2: //Mutinous { msg = string.Format("{0} has become mutinous", crew.name); kStat.OldTrait = crew.experienceTrait.Title; crew.type = ProtoCrewMember.KerbalType.Tourist; KerbalRoster.SetExperienceTrait(crew, "Tourist"); kStat.IsGrouchy = true; LifeSupportManager.Instance.TrackKerbal(kStat); DestroyRandomPart(v); } break; case 3: //Return to KSC msg = string.Format("{0} gets fed up and wanders back to the KSC", crew.name); LifeSupportManager.Instance.UntrackKerbal(crew.name); crew.rosterStatus = ProtoCrewMember.RosterStatus.Available; DestroyVessel(v); break; case 4: //Despawn msg = string.Format("{0} has gone missing", crew.name); LifeSupportManager.Instance.UntrackKerbal(crew.name); crew.rosterStatus = ProtoCrewMember.RosterStatus.Missing; DestroyVessel(v); break; case 5: //Kill msg = string.Format("{0} has died", crew.name); LifeSupportManager.Instance.UntrackKerbal(crew.name); crew.rosterStatus = ProtoCrewMember.RosterStatus.Dead; DestroyVessel(v); break; } ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER); }
public override void OnFixedUpdate() { base.OnFixedUpdate(); if (IsEnabled && myAttachedReactor != null && FNRadiator.hasRadiatorsForVessel(vessel)) { updateGeneratorPower(); double electricdt = 0; double electricdtps = 0; double max_electricdtps = 0; double input_power = 0; double currentmegajoulesSpareCapacity = TimeWarp.fixedDeltaTime > 1 || !PluginHelper.MatchDemandWithSupply ? getSpareResourceCapacity(FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime : getTotalResourceCapacity(FNResourceManager.FNRESOURCE_MEGAJOULES); double electrical_power_currently_needed = (getCurrentUnfilledResourceDemand(FNResourceManager.FNRESOURCE_MEGAJOULES) + currentmegajoulesSpareCapacity); if (!chargedParticleMode) { double carnotEff = 1.0 - coldBathTemp / hotBathTemp; totalEff = carnotEff * pCarnotEff; if (totalEff <= 0 || coldBathTemp <= 0 || hotBathTemp <= 0 || maxThermalPower <= 0) { return; } double thermal_power_currently_needed = electrical_power_currently_needed / totalEff; double thermaldt = Math.Max(Math.Min(maxThermalPower, thermal_power_currently_needed) * TimeWarp.fixedDeltaTime, 0.0); input_power = consumeFNResource(thermaldt, FNResourceManager.FNRESOURCE_THERMALPOWER); if (input_power < thermaldt) { input_power += consumeFNResource(thermaldt - input_power, FNResourceManager.FNRESOURCE_CHARGED_PARTICLES); } double wastedt = input_power * totalEff; consumeFNResource(wastedt, FNResourceManager.FNRESOURCE_WASTEHEAT); electricdt = input_power * totalEff; electricdtps = Math.Max(electricdt / TimeWarp.fixedDeltaTime, 0.0); max_electricdtps = maxThermalPower * totalEff; } else { totalEff = 0.85; double charged_power_currently_needed = electrical_power_currently_needed / totalEff; input_power = consumeFNResource(Math.Max(charged_power_currently_needed * TimeWarp.fixedDeltaTime, 0), FNResourceManager.FNRESOURCE_CHARGED_PARTICLES); electricdt = input_power * totalEff; electricdtps = Math.Max(electricdt / TimeWarp.fixedDeltaTime, 0.0); double wastedt = input_power * totalEff; max_electricdtps = maxChargedPower * totalEff; consumeFNResource(wastedt, FNResourceManager.FNRESOURCE_WASTEHEAT); //supplyFNResource(wastedt, FNResourceManager.FNRESOURCE_WASTEHEAT); } outputPower = -(float)supplyFNResourceFixedMax(electricdtps * TimeWarp.fixedDeltaTime, max_electricdtps * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime; } else { if (IsEnabled && !vessel.packed) { if (!FNRadiator.hasRadiatorsForVessel(vessel)) { IsEnabled = false; Debug.Log("[WarpPlugin] Generator Shutdown: No radiators available!"); ScreenMessages.PostScreenMessage("Generator Shutdown: No radiators available!", 5.0f, ScreenMessageStyle.UPPER_CENTER); } if (myAttachedReactor == null) { IsEnabled = false; Debug.Log("[WarpPlugin] Generator Shutdown: No reactor available!"); ScreenMessages.PostScreenMessage("Generator Shutdown: No reactor available!", 5.0f, ScreenMessageStyle.UPPER_CENTER); } } } }
public void GenerateModControlFile(bool whitelistMode) { string gameDataDir = Client.dmpClient.gameDataDir; string[] topLevelFiles = Directory.GetFiles(gameDataDir); string[] modDirectories = Directory.GetDirectories(gameDataDir); List <string> requiredFiles = new List <string>(); List <string> optionalFiles = new List <string>(); List <string> partsList = Common.GetStockParts(); //If whitelisting, add top level dll's to required (It's usually things like modulemanager) foreach (string dllFile in topLevelFiles) { if (Path.GetExtension(dllFile).ToLower() == ".dll") { requiredFiles.Add(Path.GetFileName(dllFile)); } } foreach (string modDirectory in modDirectories) { string lowerDirectoryName = modDirectory.Substring(modDirectory.ToLower().IndexOf("gamedata") + 9).ToLower(); if (lowerDirectoryName.StartsWith("squad")) { continue; } if (lowerDirectoryName.StartsWith("nasamission")) { continue; } if (lowerDirectoryName.StartsWith("darkmultiplayer")) { continue; } bool modIsRequired = false; string[] partFiles = Directory.GetFiles(Path.Combine(gameDataDir, modDirectory), "*", SearchOption.AllDirectories); List <string> modDllFiles = new List <string>(); List <string> modPartCfgFiles = new List <string>(); foreach (string partFile in partFiles) { bool fileIsPartFile = false; string relativeFileName = partFile.Substring(partFile.ToLower().IndexOf("gamedata") + 9).Replace(@"\", "/"); if (Path.GetExtension(partFile).ToLower() == ".cfg") { ConfigNode cn = ConfigNode.Load(partFile); if (cn == null) { continue; } foreach (ConfigNode partNode in cn.GetNodes("PART")) { string partName = partNode.GetValue("name"); if (partName != null) { DarkLog.Debug("Part detected in " + relativeFileName + " , name: " + partName); partName = partName.Replace('_', '.'); modIsRequired = true; fileIsPartFile = true; partsList.Add(partName); } } } if (fileIsPartFile) { modPartCfgFiles.Add(relativeFileName); } if (Path.GetExtension(partFile).ToLower() == ".dll") { modDllFiles.Add(relativeFileName); } } if (modIsRequired) { if (modDllFiles.Count > 0) { //If the mod as a plugin, just require that. It's clear enough. requiredFiles.AddRange(modDllFiles); } else { //If the mod does *not* have a plugin (Scoop-o-matic is an example), add the part files to required instead. requiredFiles.AddRange(modPartCfgFiles); } } else { if (whitelistMode) { optionalFiles.AddRange(modDllFiles); } } } string modFileData = Common.GenerateModFileStringData(requiredFiles.ToArray(), optionalFiles.ToArray(), whitelistMode, new string[0], partsList.ToArray()); string saveModFile = Path.Combine(Client.dmpClient.kspRootPath, "DMPModControl.txt"); using (StreamWriter sw = new StreamWriter(saveModFile, false)) { sw.Write(modFileData); } ScreenMessages.PostScreenMessage("DMPModFile.txt file generated in your KSP folder", 5f, ScreenMessageStyle.UPPER_CENTER); }
public static void checkPrice(string refBodyName, double SMA) { ScreenMessages.PostScreenMessage(refBodyName, 5.0f, ScreenMessageStyle.UPPER_CENTER); if (refBodyName == "Kerbin") { setPriceKer(); } if (refBodyName == "Mun") { setPriceMun(); } if (refBodyName == "Minmus") { setPriceMinmus(); } if (refBodyName == "Duna") { setPriceDuna(); } if (refBodyName == "Ike") { setPriceIke(); } if (refBodyName == "Eve") { setPriceEve(); } if (refBodyName == "Gilly") { setPriceGilly(); } if (refBodyName == "Moho") { setPriceMoho(); } if (refBodyName == "Dres") { setPriceDres(); } if (refBodyName == "Eeloo") { setPriceEeloo(); } if (refBodyName == "Jool") { setPriceJool(); } if (refBodyName == "Laythe") { setPriceLaythe(); } if (refBodyName == "Vall") { setPriceVall(); } if (refBodyName == "Bop") { setPriceBop(); } if (refBodyName == "Tylo") { setPriceTylo(); } if (refBodyName == "Pol") { setPricePol(); } if (refBodyName == "Sun" && SMA > 1000000000) { setPriceSunHigh(); } if (refBodyName == "Sun" && SMA < 1000000000) { setPriceSunLow(); } }
public override void OnUpdate() { if (!CheatOptions.InfiniteElectricity && !isChargingForJumpstart && !isSwappingFuelMode && getCurrentResourceDemand(ResourceManager.FNRESOURCE_MEGAJOULES) > getStableResourceSupply(ResourceManager.FNRESOURCE_MEGAJOULES) && getResourceBarRatio(ResourceManager.FNRESOURCE_MEGAJOULES) < 0.1 && IsEnabled && !fusion_alert) { ScreenMessages.PostScreenMessage("Warning: Fusion Reactor plasma heating cannot be guaranteed, reducing power requirements is recommended.", 10.0f, ScreenMessageStyle.UPPER_CENTER); fusion_alert = true; } else { fusion_alert = false; } if (isChargingField.guiActive) { accumulatedChargeStr = PluginHelper.getFormattedPowerString(accumulatedElectricChargeInMW, "0.0", "0.000") + " / " + PluginHelper.getFormattedPowerString(StartupPower, "0.0", "0.000"); } else if (part.vessel.geeForce > startupMaximumGeforce) { accumulatedChargeStr = part.vessel.geeForce.ToString("0.000") + "g > " + startupMaximumGeforce + "g"; } else { accumulatedChargeStr = String.Empty; } Fields["accumulatedChargeStr"].guiActive = plasma_ratio < 1; electricPowerMaintenance = PluginHelper.getFormattedPowerString(power_consumed) + " / " + PluginHelper.getFormattedPowerString(LaserPowerRequirements); if (startupAnimation != null && !initialized) { if (IsEnabled) { //animationScalar = startupAnimation.GetScalar; if (animationStarted == 0) { startupAnimation.ToggleAction(new KSPActionParam(KSPActionGroup.Custom01, KSPActionType.Activate)); animationStarted = Planetarium.GetUniversalTime(); } else if (!startupAnimation.IsMoving()) { startupAnimation.ToggleAction(new KSPActionParam(KSPActionGroup.Custom01, KSPActionType.Deactivate)); animationStarted = 0; initialized = true; isDeployed = true; } } else // Not Enabled { // continiously start startupAnimation.ToggleAction(new KSPActionParam(KSPActionGroup.Custom01, KSPActionType.Activate)); startupAnimation.ToggleAction(new KSPActionParam(KSPActionGroup.Custom01, KSPActionType.Deactivate)); } } else if (startupAnimation == null) { isDeployed = true; } // call base class base.OnUpdate(); }