private static void PostfixBoardSeat(KerbalEVA __instance, bool __result, KerbalSeat seat) { if (__result) { ExternalSeatEvent.onExternalSeatBoard.Fire(seat.vessel, KerbalVesselId, KerbalName); } }
private static void PrefixBoardSeat(KerbalEVA __instance, KerbalSeat seat) { if (__instance.vessel != null) { KerbalVesselId = __instance.vessel.id; KerbalName = __instance.vessel.vesselName; } }
public bool leavingSeat = false; // Whether the kerbal is about to leave their seat. #endregion #region Field definitions // [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "#LOC_BDArmory_EjectOnImpendingDoom", // Eject if doomed // groupName = "pilotAI_Ejection", groupDisplayName = "#LOC_BDArmory_PilotAI_Ejection", groupStartCollapsed = true), // UI_FloatRange(minValue = 0f, maxValue = 1f, stepIncrement = 0.02f, scene = UI_Scene.All)] // public float ejectOnImpendingDoom = 0.2f; // Time to impact at which to eject. #endregion /// <summary> /// Begin managing a crew member in a part. /// </summary> /// <param name="crew">The proto crew member.</param> /// <param name="part">The part.</param> public IEnumerator Configure(ProtoCrewMember crew, Part part) { if (crew == null) { Debug.LogError("[KerbalSafety]: Cannot manage null crew."); Destroy(this); yield break; } if (part == null) { Debug.LogError("[KerbalSafety]: Crew cannot exist outside of a part."); Destroy(this); yield break; } while (!part.vessel.loaded) { yield return(new WaitForFixedUpdate()); // Wait for the vessel to be loaded. (Avoids kerbals not being registered in seats.) } kerbalName = crew.displayName; this.crew = crew; this.crew.ResetInventory(); // Reset the inventory to a chute and a jetpack. this.part = part; if (part.IsKerbalEVA()) { this.kerbalEVA = part.GetComponent <KerbalEVA>(); if (kerbalEVA.IsSeated()) { var seats = part.vessel.FindPartModulesImplementing <KerbalSeat>(); bool found = false; foreach (var s in seats) { if (s.Occupant == part) { seat = s; found = true; break; } } if (!found) { Debug.LogError("[KerbalSafety]: Failed to find the kerbal seat that " + kerbalName + " occupies."); yield break; } } else // Free-falling EVA kerbal. { ejected = true; } chute = kerbalEVA.vessel.FindPartModuleImplementing <ModuleEvaChute>(); if (chute != null) { chute.deploymentState = ModuleEvaChute.deploymentStates.STOWED; // Make sure the chute is stowed. } } AddHandlers(); KerbalSafetyManager.Instance.kerbals.Add(crew, this); Debug.Log("[KerbalSafety]: Managing the safety of " + kerbalName + " in " + part.vessel.vesselName + "."); }
private static void PrefixBoardSeat(KerbalEVA __instance, ref bool __result, KerbalSeat seat) { if (__instance.vessel != null) { KerbalVesselPersistentId = __instance.vessel.persistentId; KerbalVesselId = __instance.vessel.id; KerbalName = __instance.vessel.vesselName; } }
/// <summary> /// Gets the nearest seat available for boarding. /// </summary> /// <param name="kerbal">The current kerbal.</param> /// <param name="maxDistance">The maximum distance.</param> /// <returns>Nearest seat.</returns> private KerbalSeat GetNearestSeat(KerbalEVA kerbal, float maxDistance) { KerbalSeat nearestSeat = null; Vessel nearestVessel = null; List <Vessel> vessels = new List <Vessel>(); // Get loaded vessels. foreach (Vessel vessel in FlightGlobals.Vessels) { if (vessel.loaded && !vessel.packed && vessel != kerbal.vessel) { vessels.Add(vessel); } } if (vessels.Count > 0) { // Get nearest vessel. if (vessels.Count > 1) { vessels.Sort((v1, v2) => (v1.transform.position - kerbal.vessel.transform.position).sqrMagnitude.CompareTo( (v2.transform.position - kerbal.vessel.transform.position).sqrMagnitude)); } nearestVessel = vessels[0]; List <KerbalSeat> seats = new List <KerbalSeat>(); // Get vessel seats available for boarding. foreach (KerbalSeat seat in nearestVessel.FindPartModulesImplementing <KerbalSeat>()) { if (seat.Occupant == null && (seat.transform.position - kerbal.vessel.transform.position).sqrMagnitude <= maxDistance) { seats.Add(seat); } } if (seats.Count > 0) { // Get nearest seat. if (seats.Count > 1) { seats.Sort((s1, s2) => (s1.transform.position - kerbal.vessel.transform.position).sqrMagnitude.CompareTo( (s2.transform.position - kerbal.vessel.transform.position).sqrMagnitude)); } nearestSeat = seats[0]; } } return(nearestSeat); }
public override void OnStartFinished(StartState state) { base.OnStartFinished(state); Actions["EjectAction"].active = false; _seatModule = part.Modules.GetModule <KerbalSeat>(); if (_seatModule == null) { Debug.LogError("[SSC_VS] KerbalSeat module not found."); return; } Actions["EjectAction"].active = true; }
public static VesselCommand CurrentCommand(this Vessel vessel) { VesselCommand currentCommand = VesselCommand.None; IList <PartModule> modules = vessel.getModulesOfType <PartModule>(); PartModule module; for (int idx = 0; idx < modules.Count; idx++) { module = modules[idx]; if (module is ModuleCommand) { ModuleCommand commandModule = module as ModuleCommand; if (commandModule.part.PartCrewCount() >= commandModule.minimumCrew) { if ( commandModule.minimumCrew > 0 || (commandModule.part.CrewCapacity > 0 && commandModule.part.protoModuleCrew.Count > 0) ) { currentCommand |= VesselCommand.Crew; } if (commandModule.minimumCrew == 0) { currentCommand |= VesselCommand.Probe; } } } if (module is KerbalSeat) { KerbalSeat seatModule = module as KerbalSeat; if (seatModule.Occupant != null) { currentCommand |= VesselCommand.Crew; } } if (currentCommand == (VesselCommand.Crew | VesselCommand.Probe)) { break; } } return(currentCommand); }
protected void setupGUI() { //Hide seat GUI seat = this.part.FindModuleImplementing <KerbalSeat>(); seat.Events["BoardSeat"].guiActive = false; seat.Events["BoardSeat"].guiActiveEditor = false; seat.Events["BoardSeat"].guiActiveUnfocused = false; //Hide probe command GUI wingCommander = this.part.FindModuleImplementing <ModuleCommand>(); wingCommander.Events["MakeReference"].guiActive = false; wingCommander.Events["MakeReference"].guiActiveUnfocused = false; wingCommander.Events["RenameVessel"].guiActive = false; //Hide decoupler GUI decoupler = this.part.FindModuleImplementing <ModuleDecouple>(); decoupler.Events["Decouple"].guiActive = false; decoupler.Events["Decouple"].guiActiveEditor = false; decoupler.Events["Decouple"].guiActiveUnfocused = false; //Hide MultiModeEngine toggle button multiModeEngine = this.part.FindModuleImplementing <MultiModeEngine>(); multiModeEngine.Events["ModeEvent"].guiActive = false; multiModeEngine.Events["ModeEvent"].guiActiveEditor = false; multiModeEngine.Events["ModeEvent"].guiActiveUnfocused = false; //Hide the Close Intake button. ModuleResourceIntake intake = this.part.FindModuleImplementing <ModuleResourceIntake>(); intake.Events["Deactivate"].guiActive = false; //Hide RCS GUI ModuleRCS rcs = this.part.FindModuleImplementing <ModuleRCS>(); rcs.Fields["realISP"].guiActive = false; rcs.Fields["rcsEnabled"].guiActive = false; //Hide hover engine gui hoverEngine = this.part.FindModuleImplementing <WBIMultiEngineHover>(); hoverEngine.SetGUIVisible(false); //Set fuel type resourceSwitcher = this.part.FindModuleImplementing <WBIResourceSwitcher>(); resourceSwitcher.Fields["shortName"].guiName = "Fuel Type"; }
public void ExternalSeatBoard(KerbalSeat seat, Guid kerbalVesselId, uint kerbalVesselPersistentId, string kerbalName) { if (VesselCommon.IsSpectating) { return; } if (seat.vessel == null) { return; } LunaLog.Log("Crew-board to an external seat detected!"); VesselRemoveSystem.Singleton.MessageSender.SendVesselRemove(kerbalVesselId); VesselRemoveSystem.Singleton.AddToKillList(kerbalVesselId, "Killing kerbal as it boarded a external seat"); LockSystem.Singleton.ReleaseAllVesselLocks(new[] { kerbalName }, kerbalVesselId); VesselProtoSystem.Singleton.MessageSender.SendVesselMessage(seat.vessel); }
protected void setupGUI() { //Hide seat GUI seat = this.part.FindModuleImplementing<KerbalSeat>(); seat.Events["BoardSeat"].guiActive = false; seat.Events["BoardSeat"].guiActiveEditor = false; seat.Events["BoardSeat"].guiActiveUnfocused = false; //Hide probe command GUI wingCommander = this.part.FindModuleImplementing<ModuleCommand>(); wingCommander.Events["MakeReference"].guiActive = false; wingCommander.Events["MakeReference"].guiActiveUnfocused = false; wingCommander.Events["RenameVessel"].guiActive = false; //Hide decoupler GUI decoupler = this.part.FindModuleImplementing<ModuleDecouple>(); decoupler.Events["Decouple"].guiActive = false; decoupler.Events["Decouple"].guiActiveEditor = false; decoupler.Events["Decouple"].guiActiveUnfocused = false; //Hide MultiModeEngine toggle button multiModeEngine = this.part.FindModuleImplementing<MultiModeEngine>(); multiModeEngine.Events["ModeEvent"].guiActive = false; multiModeEngine.Events["ModeEvent"].guiActiveEditor = false; multiModeEngine.Events["ModeEvent"].guiActiveUnfocused = false; //Hide the Close Intake button. ModuleResourceIntake intake = this.part.FindModuleImplementing<ModuleResourceIntake>(); intake.Events["Deactivate"].guiActive = false; //Hide RCS GUI ModuleRCS rcs = this.part.FindModuleImplementing<ModuleRCS>(); rcs.Fields["realISP"].guiActive = false; rcs.Events["Disable"].guiActive = false; //Hide hover engine gui hoverEngine = this.part.FindModuleImplementing<WBIMultiEngineHover>(); hoverEngine.SetGUIVisible(false); //Set fuel type resourceSwitcher = this.part.FindModuleImplementing<WBIResourceSwitcher>(); resourceSwitcher.Fields["shortName"].guiName = "Fuel Type"; }
public override VesselControlState UpdateControlSourceState() { this.commCapable = false; bool isHibernating = this.IsHibernating; var ksList = this.part.Modules.OfType <KerbalSeat>(); KerbalSeat ks = this.part.Modules.OfType <KerbalSeat>().First(); // KerbalEVA kev; // Part seatParent = null; if (ks == null) { Log.Error("Can't find KerbalSeat in part: " + this.part.partInfo.title); this.controlSrcStatusText = "No Crew"; this.moduleState = ModuleCommand.ModuleControlState.NotEnoughCrew; return(VesselControlState.Kerbal); } this.pilots = (this.crewCount = (this.totalCrewCount = 0)); // Kerbal kerbal = null; ProtoCrewMember pcm = null; #if false foreach (var k in ksList) { if (k.Occupant != null) { foreach (var k2 in k.Occupant.Modules.OfType <KerbalEVA>()) { if (k2 != null) { seatParent = getModulePartParent("KerbalEVA", keva); } } } } #endif if (ks.Occupant != null) { KerbalEVA keva = ks.Occupant.Modules.OfType <KerbalEVA>().FirstOrDefault(); if (keva != null) { var seatParentList = getModulePartParent("KerbalEVA", keva); if (seatParentList != null) { foreach (var seatParent in seatParentList) { Log.Info("seatParent: " + seatParent.partInfo.title + " seatParent.protoModuleCrew.count: " + seatParent.protoModuleCrew.Count().ToString()); foreach (var p in seatParent.protoModuleCrew) { Log.Info("Looking for: " + ks.Occupant.partInfo.title + " p.name: " + p.name); if (p.name == ks.Occupant.partInfo.title) { // Look for a crew member, if possible if (pcm == null || (pcm != null && pcm.type == ProtoCrewMember.KerbalType.Tourist && p.type == ProtoCrewMember.KerbalType.Crew)) { pcm = p; } // If not a pilot, keep looking if (p.type == ProtoCrewMember.KerbalType.Crew && p.HasEffect <FullVesselControlSkill>() && !p.inactive) { pcm = p; break; } //if (pcm.type == ProtoCrewMember.KerbalType.Crew && pcm.HasEffect<FullVesselControlSkill>() && !pcm.inactive) //break; } } } } } } else { Log.Info("No occupant in any seat"); Log.Info("this.vessel.name: " + this.vessel.name); Log.Info("FlightGlobals.ActiveVessel.name: " + FlightGlobals.ActiveVessel.name); this.controlSrcStatusText = "No Crew"; this.moduleState = ModuleCommand.ModuleControlState.NotEnoughCrew; return(VesselControlState.Kerbal); } if (pcm != null) { if (pcm.HasEffect <FullVesselControlSkill>() && !pcm.inactive) { this.pilots = 1; } if (pcm.type != ProtoCrewMember.KerbalType.Tourist) { this.totalCrewCount = 1; if (!pcm.inactive) { this.crewCount = 1; } } } else { if (ks.Occupant != null) { Log.Error("Unable to find Kerbal: " + ks.Occupant.partInfo.title + " in crew list"); } else { Log.Error("Unable to find Kerbal in crew list"); } this.controlSrcStatusText = "No Crew"; this.moduleState = ModuleCommand.ModuleControlState.NotEnoughCrew; return(VesselControlState.Kerbal); } if (this.crewCount == 0) { if (pcm.type == ProtoCrewMember.KerbalType.Tourist) { this.controlSrcStatusText = "Tourists Need Crew"; this.moduleState = ModuleCommand.ModuleControlState.TouristCrew; return(VesselControlState.Kerbal); } this.controlSrcStatusText = "No Crew"; this.moduleState = ModuleCommand.ModuleControlState.NotEnoughCrew; return(VesselControlState.Kerbal); } bool pilotNeededNotAvail = this.requiresPilot && this.pilots == 0; this.commCapable = true; if (CommNetScenario.CommNetEnabled && CommNetScenario.Instance != null) { bool connectionNeededAndConnected = this.Connection != null && this.Connection.IsConnected; if (!this.remoteControl && !connectionNeededAndConnected && pilotNeededNotAvail) { if (this.controlSrcStatusText != "No Pilot") { this.controlSrcStatusText = "No Pilot"; } this.moduleState = ModuleCommand.ModuleControlState.PartialManned; return(VesselControlState.KerbalPartial); } if (!connectionNeededAndConnected) { if (this.totalCrewCount == 0) { if (this.SignalRequired || !this.remoteControl) { if (this.controlSrcStatusText != "No Telemetry") { this.controlSrcStatusText = "No Telemetry"; } this.moduleState = ModuleCommand.ModuleControlState.NoControlPoint; return(VesselControlState.Probe); } if (this.requiresTelemetry) { if (this.controlSrcStatusText != "Partial Control") { this.controlSrcStatusText = "Partial Control"; } this.moduleState = ModuleCommand.ModuleControlState.PartialProbe; return(VesselControlState.ProbePartial); } } } } if (isHibernating) { if (this.controlSrcStatusText != "Hibernating") { this.controlSrcStatusText = "Hibernating"; } if (this.minimumCrew > 0) { this.moduleState = ModuleCommand.ModuleControlState.PartialManned; return(VesselControlState.KerbalPartial); } this.moduleState = ModuleCommand.ModuleControlState.PartialProbe; return(VesselControlState.ProbePartial); } else { if (this.controlSrcStatusText != "Operational") { this.controlSrcStatusText = "Operational"; } this.moduleState = ModuleCommand.ModuleControlState.Nominal; if (this.minimumCrew > 0) { return(VesselControlState.KerbalFull); } return(VesselControlState.ProbeFull); } }
internal static string DisplayVesselResourceTotals(string selectedResource) { string displayAmount = ""; double currAmount = 0; double totAmount = 0; try { if (selectedResource != "Crew" && selectedResource != "Science") { foreach (Part part in SMAddon.smController._partsByResource[selectedResource]) { currAmount += part.Resources[selectedResource].amount; totAmount += part.Resources[selectedResource].maxAmount; } } else if (selectedResource == "Crew") { currAmount = (double)SMAddon.smController.Vessel.GetCrewCount(); totAmount = (double)SMAddon.smController.Vessel.GetCrewCapacity(); // Now check for occupied external seats // external seats that are occupied will show up in getcrewcount and getcrewcapacity // Since we cannot yet xfer external crew, we need to remove them from the count.. foreach (Part iPart in SMAddon.smController.Vessel.parts) { if (iPart.Modules.Contains("KerbalSeat")) { foreach (PartModule iModule in iPart.Modules) { if (iModule.ClassName == "KerbalSeat") { KerbalSeat kSeat = (KerbalSeat)iModule; if (kSeat.Occupant != null) { currAmount -= 1; totAmount -= 1; } } } } } } else if (selectedResource == "Science") { foreach (Part part in SMAddon.smController._partsByResource[selectedResource]) { foreach (PartModule module in part.Modules) { if (module is IScienceDataContainer) { currAmount += (double)((IScienceDataContainer)module).GetScienceCount(); } } } } if (selectedResource != "Science") { displayAmount = string.Format(" - ({0}/{1})", currAmount.ToString("#######0"), totAmount.ToString("######0")); } else { displayAmount = string.Format(" - ({0})", currAmount.ToString("#######0")); } } catch (Exception ex) { LogMessage(String.Format(" in DisplayResourceTotals(). Error: {0}", ex.ToString()), "Error", true); } return(displayAmount); }
/// <summary> /// Addon work logic. /// </summary> public void Update() { if (FlightGlobals.ActiveVessel.isEVA) { string message = string.Empty; if (Input.GetKeyDown(BoardKey)) { // Prevent addon on map view, or when kerbal is busy, // or when player is typing text in some text field. if (MapView.MapIsEnabled || !this.CrewCanBoard(FlightGlobals.ActiveVessel.evaController)) { return; } this.AllowMessages = true; this.WantsBoard = !this.WantsBoard; if (this.WantsBoard) { this.KerbalName = FlightGlobals.ActiveVessel.vesselName; } message = this.GetStatusMessage(); } KerbalEVA kerbal = FlightGlobals.ActiveVessel.evaController; if (this.WantsBoard && kerbal != null) { Part airlockPart = this.GetKerbalAirlock(kerbal); if (this.AirlockPart != airlockPart) { // Keep previous airlock to avoid multiple attemts to board it. this.AirlockPart = airlockPart; if (airlockPart != null && kerbal.vessel.state == Vessel.State.ACTIVE && !kerbal.vessel.packed) { if (airlockPart.protoModuleCrew.Count < airlockPart.CrewCapacity) { // There is enough place for the kerbal, // boarding should be successful. We can reset addon fields. this.AllowMessages = false; this.AddonReset(); } // Try board. kerbal.BoardPart(airlockPart); return; } } // Try board nearest seat when no airlock. if (airlockPart == null) { KerbalSeat seat = this.GetNearestSeat(kerbal, Input.GetKeyDown(BoardKey) ? OriginalSeatDistance : SeatDistance); if (seat != null) { this.AllowMessages = false; seat.BoardSeat(); // Check whether boarding seat was successful. if (((PartModule)seat).Events["BoardSeat"].active) { // Fail case. this.AllowMessages = true; } else { // Success case. this.AddonReset(); } } } } this.DisplayMessage(message); } }
// [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "#LOC_BDArmory_EjectOnImpendingDoom", // Eject if doomed // groupName = "pilotAI_Ejection", groupDisplayName = "#LOC_BDArmory_PilotAI_Ejection", groupStartCollapsed = true), // UI_FloatRange(minValue = 0f, maxValue = 1f, stepIncrement = 0.02f, scene = UI_Scene.All)] // public float ejectOnImpendingDoom = 0.2f; // Time to impact at which to eject. #endregion /// <summary> /// Begin managing a crew member in a part. /// </summary> /// <param name="crew">The proto crew member.</param> /// <param name="part">The part.</param> public IEnumerator Configure(ProtoCrewMember crew, Part part, bool quiet = false) { if (crew == null) { Debug.LogError("[BDArmory.KerbalSafety]: Cannot manage null crew."); Destroy(this); yield break; } if (part == null) { Debug.LogError("[BDArmory.KerbalSafety]: Crew cannot exist outside of a part."); Destroy(this); yield break; } while (!part.vessel.loaded) { yield return(new WaitForFixedUpdate()); // Wait for the vessel to be loaded. (Avoids kerbals not being registered in seats.) } kerbalName = crew.displayName; this.crew = crew; switch (BDArmorySettings.KERBAL_SAFETY_INVENTORY) { case 1: this.crew.ResetInventory(true); // Reset the inventory to the default of a chute and a jetpack. break; case 2: this.crew.ResetInventory(false); // Reset the inventory to just a chute. break; } this.part = part; if (part.IsKerbalEVA()) { this.kerbalEVA = part.GetComponent <KerbalEVA>(); if (kerbalEVA.IsSeated()) { var seats = part.vessel.FindPartModulesImplementing <KerbalSeat>(); bool found = false; foreach (var s in seats) { if (s.Occupant == part) { seat = s; found = true; break; } } if (!found) { Debug.LogError("[BDArmory.KerbalSafety]: Failed to find the kerbal seat that " + kerbalName + " occupies."); yield break; } } else // Free-falling EVA kerbal. { ejected = true; StartCoroutine(DelayedChuteDeployment()); StartCoroutine(RecoverWhenPossible()); } ConfigureKerbalEVA(kerbalEVA); } AddHandlers(); KerbalSafetyManager.Instance.kerbals.Add(crew, this); if (!quiet) { Debug.Log("[BDArmory.KerbalSafety]: Managing the safety of " + kerbalName + (ejected ? " on EVA" : " in " + part.vessel.vesselName) + "."); } OnVesselModified(part.vessel); // Immediately check the vessel. }
void OnEnable() { if (parentPart == null) { gameObject.SetActive(false); return; } hasFuel = true; startTime = Time.time; engine = parentPart.FindModuleImplementing <ModuleEngines>(); var leak = parentPart.FindModuleImplementing <ModuleDrainFuel>(); if (leak != null) { leak.drainDuration = 0; } foreach (var existingLeakFX in parentPart.GetComponentsInChildren <FuelLeakFX>()) { existingLeakFX.lifeTime = 0; //kill leak FX } BDArmorySetup.numberOfParticleEmitters++; pEmitters = gameObject.GetComponentsInChildren <KSPParticleEmitter>(); using (var pe = pEmitters.AsEnumerable().GetEnumerator()) while (pe.MoveNext()) { if (pe.Current == null) { continue; } pe.Current.emit = true; _highestEnergy = pe.Current.maxEnergy; EffectBehaviour.AddParticleEmitter(pe.Current); } Seat = null; if (parentPart.parent != null) { var kerbalSeats = parentPart.parent.Modules.OfType <KerbalSeat>(); if (kerbalSeats.Count() > 0) { Seat = kerbalSeats.First(); } } if (parentPart.protoModuleCrew.Count > 0) //crew can extingusih fire { burnTime = 10; } if (parentPart.parent != null && parentPart.parent.protoModuleCrew.Count > 0 || (Seat != null && Seat.Occupant != null)) { burnTime = 20; //though adjacent parts will take longer to get to and extingusih } if (!surfaceFire) { if (parentPart.GetComponent <ModuleSelfSealingTank>() != null) { ModuleSelfSealingTank FBX; FBX = parentPart.GetComponent <ModuleSelfSealingTank>(); if (FBX.FireBottles > 0) { FBX.FireBottles -= 1; if (engine != null && engine.EngineIgnited && engine.allowRestart) { engine.Shutdown(); enginerestartTime = Time.time; } burnTime = 10; Misc.Misc.RefreshAssociatedWindows(parentPart); Debug.Log("[FireFX] firebottles remianing in " + parentPart.name + ": " + FBX.FireBottles); } else { if (engine != null && engine.EngineIgnited && engine.allowRestart) { if (parentPart.vessel.verticalSpeed < 30) //not diving/trying to climb. With the vessel registry, could also grab AI state to add a !evading check { engine.Shutdown(); enginerestartTime = Time.time + 10; burnTime = 20; } //though if it is diving, then there isn't a second call to cycle engines. Add an Ienumerator to check once every couple sec? } } } } }
/// <summary> /// Update is called once per frame. /// </summary> public void Update() { this.CheckVesselControl(); if (FlightGlobals.ActiveVessel.isEVA) { string message = string.Empty; KerbalEVA kerbal = FlightGlobals.ActiveVessel.evaController; if (kerbal == null) { return; } if (Input.GetKeyUp(this.BoardKey)) { // Prevent addon on map view, or when kerbal is busy, // or when player is typing text in some text field. if (!this.CanKerbalStartToWant(kerbal)) { return; } this.AllowMessages = true; this.WantsToBoard = !this.WantsToBoard; if (this.WantsToBoard) { this.KerbalName = FlightGlobals.ActiveVessel.vesselName; } message = this.GetStatusMessage(this.WantsToBoard ? WantsToBoardMessage : HesitatingMessage); } if (Input.GetKeyUp(this.GrabKey) && !kerbal.OnALadder) { string pattern = "[" + this.GrabKey.ToString() + "]:"; bool canGrabNow = false; ScreenMessages screenMessages = GameObject.FindObjectOfType <ScreenMessages>(); foreach (var activeMessage in screenMessages.ActiveMessages) { if (activeMessage.message.StartsWith(pattern, StringComparison.InvariantCultureIgnoreCase)) { canGrabNow = true; break; } } if (!canGrabNow) { // Prevent addon on map view, or when kerbal is busy, // or when player is typing text in some text field. if (!this.CanKerbalStartToWant(kerbal)) { return; } this.AllowMessages = true; this.WantsToGrab = !this.WantsToGrab; if (this.WantsToGrab) { this.KerbalName = FlightGlobals.ActiveVessel.vesselName; } message = this.GetStatusMessage(this.WantsToGrab ? WantsToGrabMessage : HesitatingMessage); } } if (this.WantsToBoard) { Part airlockPart = this.GetKerbalAirlock(kerbal); if (this.AirlockPart != airlockPart) { // Keep previous airlock to avoid multiple attemts to board it. this.AirlockPart = airlockPart; if (airlockPart != null && kerbal.vessel.state == Vessel.State.ACTIVE && !kerbal.vessel.packed) { if (airlockPart.protoModuleCrew.Count < airlockPart.CrewCapacity) { // There is enough place for the kerbal, // boarding should be successful. We can reset addon fields. this.AllowMessages = false; this.AddonReset(); } // Try board. this.LockVesselControl(); kerbal.BoardPart(airlockPart); return; } } // Try board nearest seat when no airlock. if (airlockPart == null) { KerbalSeat seat = this.GetNearestSeat(kerbal, Input.GetKeyUp(this.BoardKey) ? OriginalSeatDistance : SeatDistance); if (seat != null) { this.AllowMessages = false; this.LockVesselControl(); seat.BoardSeat(); // Check whether boarding seat was successful. if (((PartModule)seat).Events["BoardSeat"].active) { // Fail case. this.AllowMessages = true; } else { // Success case. this.AddonReset(); return; } } } } if (this.WantsToGrab && !kerbal.OnALadder) { ScreenMessages screenMessages = GameObject.FindObjectOfType <ScreenMessages>(); foreach (var activeMessage in screenMessages.ActiveMessages) { if (activeMessage.message.EndsWith("]: Grab", StringComparison.InvariantCultureIgnoreCase)) { foreach (var stateEvent in kerbal.fsm.CurrentState.StateEvents) { if (stateEvent.name == "Ladder Grab Start") { this.AllowMessages = false; this.WantsToGrab = false; this.LockVesselControl(); kerbal.fsm.RunEvent(stateEvent); break; } } break; } } } this.DisplayMessage(message); } }