/// <summary> /// Gets the state of a docking port. Does not consider the state of an attached docking port. /// </summary> static DockingPortState IndividualState(ModuleDockingNode node) { var state = node.state; if (state == "Ready") { return(DockingPortState.Ready); } if (state.StartsWith("Docked", StringComparison.CurrentCulture) || state == "PreAttached") { return(DockingPortState.Docked); } if (state.Contains("Acquire")) { return(DockingPortState.Docking); } if (state == "Disengage") { return(DockingPortState.Undocking); } if (state == "Disabled") { var shieldModule = node.part.Module <ModuleAnimateGeneric> (); if (shieldModule == null) { throw new InvalidOperationException("Docking port state is '" + node.state + "', but it does not have a shield!"); } return(shieldModule.status.StartsWith("Moving", StringComparison.CurrentCulture) ? DockingPortState.Moving : DockingPortState.Shielded); } throw new ArgumentException("Unknown docking port state '" + node.state + "'"); }
public override void OnStart(StartState state) { base.OnStart(state); if (fixedUpdateHelper == null && HighLogic.LoadedSceneIsFlight) { fixedUpdateHelper = this.part.gameObject.AddComponent <FixedUpdateHelper>(); fixedUpdateHelper.onFixedUpdateDelegate = OnUpdateFixed; fixedUpdateHelper.enabled = true; } ModuleDockingNode dockingNode = this.part.FindModuleImplementing <ModuleDockingNode>(); if (!dockingNode) { return; } if (dockingNode.isEnabled) { Events["ToggleDockingPort"].guiName = "Disable Docking Port"; } else { Events["ToggleDockingPort"].guiName = "Enable Docking Port"; } }
// This method allows us to check if a specified ModuleDockingNode is one that this hatch is attached to internal bool IsRelatedDockingNode(ModuleDockingNode dockNode) { if (dockNode.nodeTransformName == docNodeTransformName) { if (string.IsNullOrEmpty(docNodeAttachmentNodeName)) { docNodeAttachmentNodeName = dockNode.referenceNode.id; } modDockNode = dockNode; return(true); } if (dockNode.referenceNode.id == docNodeAttachmentNodeName) { if (string.IsNullOrEmpty(docNodeTransformName)) { docNodeTransformName = dockNode.nodeTransformName; } modDockNode = dockNode; return(true); } // If we are here, we have an orphaned hatch. we may be able to recover if the part only has one docking module... // TODO, check for dups in the same part... if (this.part.FindModulesImplementing <ModuleDockingNode>().Count == 1) { // we are good. lets fix the hatch and continue modDockNode = this.part.FindModulesImplementing <ModuleDockingNode>().First(); docNodeTransformName = modDockNode.nodeTransformName; docNodeAttachmentNodeName = modDockNode.referenceAttachNode; return(true); } return(false); }
/// <summary> /// Convert the textual docking node state into an enum, so we don't /// need to do string compares. /// </summary> /// <param name="whichNode"></param> /// <returns></returns> internal static DockingNodeState GetNodeState(ModuleDockingNode whichNode) { if (whichNode == null) { return(DockingNodeState.UNKNOWN); } switch (whichNode.state) { case "PreAttached": return(DockingNodeState.PREATTACHED); case "Docked (docker)": return(DockingNodeState.DOCKED); case "Docked (dockee)": return(DockingNodeState.DOCKED); case "Ready": return(DockingNodeState.READY); default: return(DockingNodeState.UNKNOWN); } }
private bool CheckModuleDockingNode() { if (null == modDockNode) { // We do not know which ModuleDockingNode we are attached to yet. Try to find one. IEnumerator <ModuleDockingNode> eNodes = part.Modules.OfType <ModuleDockingNode>().GetEnumerator(); while (eNodes.MoveNext()) { if (eNodes.Current == null) { continue; } if (IsRelatedDockingNode(eNodes.Current)) { modDockNode = eNodes.Current; return(true); } } eNodes.Dispose(); } else { return(true); } return(false); }
// Adapted from KIS by IgorZ // See https://github.com/ihsoft/KIS/blob/master/Source/KIS_Shared.cs#L1005-L1039 // This method is in the public domain. /// <summary>Couples docking port with a part at its reference attach node.</summary> /// <remarks>Both parts must be already connected and the attach nodes correctly set.</remarks> /// <param name="dockingNode">Port to couple.</param> /// <returns><c>true</c> if coupling was successful.</returns> public static bool CoupleDockingPortWithPart(ModuleDockingNode dockingNode) { Part tgtPart = dockingNode.referenceNode.attachedPart; if (tgtPart == null) { log.error("Node's part " + dockingNode.part.name + " is not attached to anything thru the reference node"); return(false); } if (dockingNode.state != dockingNode.st_ready.name) { log.debug("Hard reset docking node " + dockingNode.part.name + " from state " + dockingNode.state + " to " + dockingNode.st_ready.name); dockingNode.dockedPartUId = 0; dockingNode.dockingNodeModuleIndex = 0; // Target part lived in real world for some time, so its state may be anything. // Do a hard reset. dockingNode.fsm.StartFSM(dockingNode.st_ready.name); } var initState = dockingNode.lateFSMStart(PartModule.StartState.None); // Make sure part init catched the new state. while (initState.MoveNext()) { // Do nothing. Just wait. } if (dockingNode.fsm.currentStateName != dockingNode.st_preattached.name) { log.warning("Node on " + dockingNode.part.name + " is unexpected state " + dockingNode.fsm.currentStateName); return(false); } log.debug("Successfully set docking node " + dockingNode.part + " to state " + dockingNode.fsm.currentStateName + " with part " + tgtPart.name); return(true); }
public void SendToPartUndockNotifyees(Part p) { // Notify any hooks attached to the part on the "from" side of the event: UniqueSetValue <UserDelegate> notifyees = GetPartUndockNotifyees(p); foreach (UserDelegate del in notifyees) { if (UserDelgateIsAcceptable(del)) { Shared.Cpu.AddTrigger(del); } } // Notify any hooks attached to the part on the "to" side of the event: ModuleDockingNode dockModule = (ModuleDockingNode)p.Modules["ModuleDockingNode"]; notifyees = GetPartUndockNotifyees(dockModule.otherNode.part); foreach (UserDelegate del in notifyees) { if (UserDelgateIsAcceptable(del)) { Shared.Cpu.AddTrigger(del); } } // The event has no data available on which other part it had been attached to, apparently. }
private bool CheckForNodeDockedToPart(ModuleDockingNode thisNode, Part otherPart) { bool retVal = false; Log.dbg("thisNode.dockedPartUId={0} otherPart.flightID={1} thisNode.state: {2}", thisNode.dockedPartUId, otherPart.flightID, thisNode.state); // if (otherPart == thisNode.part.vessel[thisNode.dockedPartUId]) if (thisNode.dockedPartUId == otherPart.flightID) { Log.dbg("IDs match"); if (thisNode.state == "Docked (dockee)") { Log.dbg(" this module is docked (dockee) to the other part"); retVal = true; } else if (thisNode.state == "Docked (docker)") { Log.dbg("this module is docked (docker) to the other part"); retVal = true; } else if (thisNode.state == "Acquire") { Log.warn("this module is in the Acquire state, which might mean it is in the process of docking."); retVal = true; } } return(retVal); }
public override void OnStart(StartState state) { base.OnStart(state); SpawnManager.Init(part); SpawnManager.SetupSensor(); if (!string.IsNullOrEmpty(ConstructionNode)) { construction_node = part.FindAttachNode(ConstructionNode); foreach (var port in part.FindModulesImplementing <ModuleDockingNode>()) { if (port.nodeTransformName == ConstructionNode || port.referenceAttachNode == ConstructionNode) { construction_port = port; break; } } } if (construction_node == null) { this.Log("ERROR: unable to find construction AttachNode with id: {}", ConstructionNode); this.EnableModule(false); return; } if (kit && ConstructDockingNode >= 0) { construct_docking_node = kit.DockingNodes[ConstructDockingNode]; } }
public static bool IsDocked(Vessel vessel, Part part) { ModuleDockingNode dockingPort = part.Modules.OfType <ModuleDockingNode>().FirstOrDefault(); //this port is docked if (dockingPort.state.Length >= 6 && dockingPort.state.Substring(0, 6) == "Docked" && null != dockingPort.vesselInfo.name) { return(true); } //no joined port filled if (dockingPort.dockedPartUId == 0) { return(false); } //find joined port foreach (Part p in vessel.parts) { if (p.flightID == dockingPort.dockedPartUId) { ModuleDockingNode pDockingPort = p.Modules.OfType <ModuleDockingNode>().FirstOrDefault(); if (pDockingPort != null && pDockingPort.state.Length >= 6 && pDockingPort.state.Substring(0, 6) == "Docked") { return(true); } } } return(false); }
// Vessel Menu private void TargetVessel(int index, TextMenu.Item ti) { if (selectedVessel == vesselsList[index].vessel) { // Already selected. Are there ports? if (UpdatePortsList() > 0) { currentMenu = MenuList.Ports; activeMenu = new TextMenu(); activeMenu.rightColumnWidth = 7; activeMenu.labelColor = nameColorTag; activeMenu.selectedColor = selectedColorTag; activeMenu.disabledColor = unavailableColorTag; activeMenu.rightTextColor = distanceColorTag; UpdateLists(); if (selectedPort != null) { int idx = portsList.FindIndex(x => x == selectedPort); activeMenu.currentSelection = idx; } } } else { vesselsList[index].SetTarget(); selectedCelestial = null; selectedPort = null; activeMenu.SetSelected(index, true); } }
public void OnDestroy() { //free referenced modules extendAnimation = null; dockingNode = null; anim = null; }
public override void OnUpdate() { if (!pageActiveState || !JUtil.VesselIsInIVA(vessel)) { return; } currentTarget = FlightGlobals.fetch.VesselTarget; selectedCelestial = currentTarget as CelestialBody; selectedVessel = currentTarget as Vessel; selectedPort = currentTarget as ModuleDockingNode; selectedClaw = currentTarget as ModuleGrappleNode; if (selectedPort != null) { selectedVessel = selectedPort.vessel; } if (selectedClaw != null) { selectedVessel = selectedClaw.vessel; } if (vessel.parts.Count != partCount) { FindReferencePoints(); //UpdateUndockablesList(); } if (!UpdateCheck()) { return; } UpdateLists(); }
/// <summary> /// Flag the lists as invalid due to craft changes / destruction. /// </summary> internal void InvalidateModuleLists() { listsInvalid = true; availableAblators.Clear(); availableAirIntakes.Clear(); availableAlternators.Clear(); availableAlternatorOutput.Clear(); availableDeployableWheels.Clear(); availableEngines.Clear(); availableFuelCells.Clear(); availableFuelCellOutput.Clear(); availableGenerators.Clear(); availableGeneratorOutput.Clear(); availableGimbals.Clear(); availableMultiModeEngines.Clear(); availableParachutes.Clear(); availableRadars.Clear(); availableRealChutes.Clear(); availableSolarPanels.Clear(); availableThrustReverser.Clear(); availableWheelBrakes.Clear(); availableWheelDamage.Clear(); mainDockingNode = null; }
private void onSnapChanged(BaseField field, System.Object obj) { ModuleDockingNode mdn = part.GetComponent <ModuleDockingNode>(); mdn.snapOffset = snapAngle; mdn.snapRotation = enableSnap; MonoBehaviour.print("Set docking node module to snap angle: " + snapAngle + " enabled: " + enableSnap); }
public void Start() { dockingNode = part.FindModuleImplementing <ModuleDockingNode>(); hasDockingNode = dockingNode != null; Fields["dockFSMState"].guiActive = Fields["dockFSMState"].guiActiveUnfocused = hasDockingNode; Fields["dockOtherNode"].guiActive = Fields["dockOtherNode"].guiActiveUnfocused = hasDockingNode; }
// Celestial Menu private void TargetCelestial(int index, TextMenu.Item ti) { celestialsList[index].SetTarget(); selectedVessel = null; selectedPort = null; activeMenu.SetSelected(index, true); }
// Space Object Menu private void TargetSpaceObject(int index, TextMenu.Item ti) { spaceObjectsList[index].SetTarget(); selectedCelestial = null; selectedPort = null; activeMenu.SetSelected(index, true); }
public void Start() { updateGUI(); ModuleDockingNode mdn = part.GetComponent <ModuleDockingNode>(); mdn.snapOffset = snapAngle; mdn.snapRotation = enableSnap; }
private void departureStage1() { if (RmmUtil.IsDocked(_vessel, _part)) { ModuleDockingNode DockNode = _part.Modules.OfType <ModuleDockingNode>().FirstOrDefault(); DockNode.Undock(); } _departureStage = 2; _nextLogicTime = Planetarium.GetUniversalTime() + 2; }
private Part getDockPart() { ModuleDockingNode mdn = part.GetComponent <ModuleDockingNode>(); if (mdn != null && mdn.otherNode != null) { return(mdn.otherNode.part); } return(null); }
public override void Load(ConfigNode node) { base.Load(node); part_node = part.FindAttachNode(NodeID); docking_node = part.Modules.GetModule <ModuleDockingNode>(); if (docking_node != null && docking_node.referenceAttachNode != NodeID) { docking_node = null; } }
bool can_restore() { //if hangar is not ready, return if (hangar_state == HangarState.Inactive) { ScreenMessager.showMessage("Activate the hangar first", 3); return(false); } if (hangar_gates.State != AnimatorState.Opened) { ScreenMessager.showMessage("Open hangar gates first", 3); return(false); } //if something is docked to the hangar docking port (if its present) ModuleDockingNode dport = part.Modules.OfType <ModuleDockingNode>().SingleOrDefault(); if (dport != null && dport.vesselInfo != null) { ScreenMessager.showMessage("Cannot launch a vessel while another is docked", 3); return(false); } //if in orbit or on the ground and not moving switch (FlightGlobals.ClearToSave()) { case ClearToSaveStatus.NOT_IN_ATMOSPHERE: { ScreenMessager.showMessage("Cannot launch a vessel while flying in atmosphere", 3); return(false); } case ClearToSaveStatus.NOT_UNDER_ACCELERATION: { ScreenMessager.showMessage("Cannot launch a vessel hangar is under accelleration", 3); return(false); } case ClearToSaveStatus.NOT_WHILE_ABOUT_TO_CRASH: { ScreenMessager.showMessage("Cannot launch a vessel while about to crush", 3); return(false); } case ClearToSaveStatus.NOT_WHILE_MOVING_OVER_SURFACE: { ScreenMessager.showMessage("Cannot launch a vessel while moving over the surface", 3); return(false); } } if (vessel.angularVelocity.magnitude > 0.003) { ScreenMessager.showMessage("Cannot launch a vessel while rotating", 3); return(false); } return(true); }
private ModuleDockingHatch GetHatchForDockingNode(ModuleDockingNode dockNode) { foreach (ModuleDockingHatch dockHatch in dockNode.part.Modules.OfType <ModuleDockingHatch>()) { if (dockHatch.modDockNode == dockNode) { return(dockHatch); } } return(null); }
private void setDockingPortTarget(ModuleDockingNode portNode) { var vessel = portNode.GetVessel(); //can't set target if the vessel is not loaded or is the active vessel if (!vessel.loaded || vessel.isActiveVessel) { return; } FlightGlobals.fetch.SetVesselTarget(portNode); }
protected static void RestoreMainCamera() { DebugOutput("RestoreMainCamera"); if (sCam != null) { sCam.transform.parent = sOrigParent; sCam.transform.localPosition = sOrigPosition; sCam.transform.localRotation = sOrigRotation; sCam.SetFoV(sOrigFov); sCam.ActivateUpdate(); if (FlightGlobals.ActiveVessel != null && HighLogic.LoadedScene == GameScenes.FLIGHT) { //sCam.SetTarget(FlightGlobals.ActiveVessel.transform, FlightCamera.TargetMode.Transform); sCam.SetTarget(FlightGlobals.ActiveVessel.transform, FlightCamera.TargetMode.Vessel); } sOrigParent = null; } if (sCurrentCamera != null) { sCurrentCamera.mt.SetCameraMode(CameraFilter.eCameraMode.Normal); sCurrentCamera.camActive = false; } sCurrentCamera = null; Camera.main.nearClipPlane = sOrigClip; ///////////////////////////////////// if (sOrigVesselTransformPart != null) { if (GameSettings.MODIFIER_KEY.GetKey(false)) { #if false ModuleDockingNode mdn = sOrigVesselTransformPart.FindModuleImplementing <ModuleDockingNode>(); if (mdn != null) { sOrigVesselTransformPart.SetReferenceTransform(mdn.controlTransform); } else #endif { // sOrigVesselTransformPart.SetReferenceTransform(sOrigVesselTransformPart.GetReferenceTransform()); } FlightGlobals.ActiveVessel.SetReferenceTransform(sOrigVesselTransformPart, true); ScreenMessages.PostScreenMessage(locControlPointRestored + " " + sOrigVesselTransformPart.partInfo.title); sOrigVesselTransformPart = null; } } ///////////////////////////////////// }
internal DockingPort(Part part) { Part = part; var internalPart = part.InternalPart; port = internalPart.Module <ModuleDockingNode> (); shield = internalPart.Module <ModuleAnimateGeneric> (); if (port == null) { throw new ArgumentException("Part is not a docking port"); } }
public void Start() { ModuleDockingNode[] dockModules = part.GetComponents <ModuleDockingNode>(); if (dockingModuleIndex >= dockModules.Length) { MonoBehaviour.print("ERROR: Could not locate docking port by index: " + dockingModuleIndex + " only found: " + dockModules.Length + " docking modules on part. Please check your part configuration for errors."); return; } ModuleDockingNode dockModule = dockModules[dockingModuleIndex]; updateDockingModuleFieldNames(dockModule, portName); }
ReferenceFrame( Type type, global::CelestialBody body = null, global::Vessel vessel = null, ManeuverNode node = null, Part part = null, ModuleDockingNode dockingPort = null) { this.type = type; this.body = body; this.vesselId = vessel != null ? vessel.id : Guid.Empty; this.node = node; //TODO: is it safe to use a part id of 0 to mean no part? this.partId = part != null ? part.flightID : 0; this.dockingPort = dockingPort; }
private bool PointToReferenceCamera() { isReferenceCamera = true; referencePart = ourVessel.GetReferenceTransformPart(); ModuleDockingNode thatPort = null; ModuleGrappleNode thatClaw = null; if (referencePart != null) { foreach (PartModule thatModule in referencePart.Modules) { thatPort = thatModule as ModuleDockingNode; thatClaw = thatModule as ModuleGrappleNode; if (thatPort != null || thatClaw != null) { break; } } } if (thatPort != null) { if (!LocateCamera(referencePart, "dockingNode")) { cameraPart = thatPort.part; cameraTransform = ourVessel.ReferenceTransform.gameObject; isReferenceTransformCamera = true; } isReferenceClawCamera = false; return(CreateCameraObjects()); } else if (thatClaw != null) { // Mihara: Dirty hack to get around the fact that claws have their reference transform inside the structure. if (LocateCamera(referencePart, "ArticulatedCap")) { isReferenceClawCamera = true; clawModule = thatClaw; } else { JUtil.LogMessage(this, "Claw was not a stock part. Falling back to reference transform position..."); cameraPart = thatClaw.part; cameraTransform = ourVessel.ReferenceTransform.gameObject; } return(CreateCameraObjects()); } else { return(false); } }
public override void OnStart(StartState st) { base.OnStart(st); dockingNode = this.part.FindModuleImplementing<ModuleDockingNode>(); //Hide the native events if (dockingNode != null) { dockingNode.Events["SetAsTarget"].guiActiveUnfocused = false; dockingNode.Events["UnsetTarget"].guiActiveUnfocused = false; //dockingNode.Events["MakeReferenceTransform"].guiActive = false; } }
private void updateDockingModules(bool start) { //TODO only remove and replace modules if the new setup differs from the old if (topDockPartModule != null) { part.RemoveModule(topDockPartModule); topDockPartModule = null; } if (bottomDockPartModule != null) { part.RemoveModule(bottomDockPartModule); bottomDockPartModule = null; } updateTopDockModule(start); updateBottomDockModule(start); }
//TODO load docking module config from sub-config nodes in the module node private void updateTopDockModule(bool start) { bool topNodeActive = topDockModule.model != null; if (topNodeActive && topDockPartModule == null) { ConfigNode topModuleNode = new ConfigNode("MODULE"); topModuleNode.AddValue("name", "ModuleDockingNode"); topModuleNode.AddValue("referenceAttachNode", topDockNode); topModuleNode.AddValue("useReferenceAttachNode", true); topModuleNode.AddValue("nodeTransformName", topDockName); topModuleNode.AddValue("controlTransformName", topDockName + "Control"); topModuleNode.AddValue("nodeType", "size0, size1"); topModuleNode.AddValue("captureRange", "0.1"); topDockPartModule = (ModuleDockingNode)part.AddModule(topModuleNode); if (start) { topDockPartModule.OnStart(StartState.Editor); } topDockPartModule.referenceNode = part.FindAttachNode(topDockNode); } else if (!topNodeActive && topDockPartModule != null) { part.RemoveModule(topDockPartModule); } if (topNodeActive) { SSTUMultiDockingPort.updateDockingModuleFieldNames(topDockPartModule, "Top Port"); } }
//Draw the right click context menu window contents private void drawContext(int windowID) { int _top = 0; if (GUI.Button(new Rect(0, _top, contextPos.width, 20), "Target Vessel", contextStyle)) { if (contextActive != null) FlightGlobals.fetch.SetVesselTarget(contextActive.vessel); contextActive = null; } _top += Mathf.RoundToInt(contextStyle.fixedHeight); if (GUI.Button(new Rect(0, _top, contextPos.width, 20), "Control Vessel", contextStyle)) { saveConfig(); //GamePersistence.SaveGame("persistent", HighLogic.SaveFolder, SaveMode.OVERWRITE); if (contextActive != null) FlightGlobals.SetActiveVessel(contextActive.vessel); contextActive = null; } _top += Mathf.RoundToInt(contextStyle.fixedHeight); const string renameStr = "Rename Vessel"; String renameHint = string.Empty; if (contextActive != null && !contextActive.vessel.loaded) { //renameStr = "Queue Vessel Rename"; renameHint = "Too far to rename"; GUI.enabled = false; } if (GUI.Button(new Rect(0, _top, contextPos.width, 20), new GUIContent(renameStr, renameHint), contextStyle)) { if (contextActive != null) contextActive.vessel.RenameVessel(); contextActive = null; } GUI.enabled = true; _top += Mathf.RoundToInt(contextStyle.fixedHeight); if (contextActive == null) return; lastActiveDockingNode = activeDockingNode; activeDockingNode = null; foreach (ModuleDockingNode m in contextActive.availableDocks) { if (Vector3.Distance(FlightGlobals.ActiveVessel.GetTransform().position, m.GetTransform().position) >= 196.0f) GUI.enabled = false; GUIStyle temp = contextStyle; if (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.Equals(m)) temp = contextStyle2; if (new Rect(0, _top, contextPos.width, 20).Contains(Event.current.mousePosition)) { m.part.SetHighlightColor(Color.red); m.part.SetHighlight(true); } else { m.part.SetHighlightDefault(); m.part.SetHighlight(false); } if (GUI.Button(new Rect(0, _top, contextPos.width, 20), "Target " + m.part.partInfo.title, temp)) { FlightGlobals.fetch.SetVesselTarget(m); m.part.SetHighlightDefault(); m.part.SetHighlight(false); contextActive = null; } GUI.enabled = true; _top += Mathf.RoundToInt(contextStyle.fixedHeight); } }
private void init(bool start) { if (initialized) { return; } initialized = true; topNodeNames = SSTUUtils.parseCSV(topManagedNodes); bottomNodeNames = SSTUUtils.parseCSV(bottomManagedNodes); ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData); coreModules = SingleModelData.parseModels(node.GetNodes("CORE")); List<ConfigNode> tops = new List<ConfigNode>(); List<ConfigNode> bottoms = new List<ConfigNode>(); ConfigNode[] mNodes = node.GetNodes("CAP"); ConfigNode mNode; int len = mNodes.Length; for (int i = 0; i < len; i++) { mNode = mNodes[i]; if (mNode.GetBoolValue("useForTop", true)) { tops.Add(mNode); } if (mNode.GetBoolValue("useForBottom", true)) { bottoms.Add(mNode); } } topModules = SingleModelData.parseModels(tops.ToArray()); bottomModules = SingleModelData.parseModels(bottoms.ToArray()); tops.Clear(); bottoms.Clear(); mNodes = node.GetNodes("DOCK"); len = mNodes.Length; for (int i = 0; i < len; i++) { mNode = mNodes[i]; if (mNode.GetBoolValue("useForTop", true)) { tops.Add(mNode); } if (mNode.GetBoolValue("useForBottom", true)) { bottoms.Add(mNode); } } topDockModules = SingleModelData.parseModels(tops.ToArray()); bottomDockModules = SingleModelData.parseModels(bottoms.ToArray()); tops.Clear(); bottoms.Clear(); mNodes = node.GetNodes("SOLAR"); len = mNodes.Length; solarModules = new SolarData[len]; for (int i = 0; i < len; i++) { mNode = mNodes[i]; solarModules[i] = new SolarData(mNode); } topDockModule = SingleModelData.findModel(topDockModules, currentTopDock); topModule = SingleModelData.findModel(topModules, currentTop); coreModule = SingleModelData.findModel(coreModules, currentCore); bottomModule = SingleModelData.findModel(bottomModules, currentBottom); bottomDockModule = SingleModelData.findModel(bottomDockModules, currentBottomDock); solarModule = Array.Find(solarModules, m => m.name == currentSolar);//TODO cleanup if (!topModule.isValidTextureSet(currentTopTexture)) { currentTopTexture = topModule.getDefaultTextureSet(); } if (!coreModule.isValidTextureSet(currentCoreTexture)) { currentCoreTexture = coreModule.getDefaultTextureSet(); } if (!bottomModule.isValidTextureSet(currentBottomTexture)) { currentBottomTexture = bottomModule.getDefaultTextureSet(); } restoreModels(); updateModulePositions(); updateMass(); updateCost(); updateAttachNodes(false); if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) { ModuleDockingNode[] mdns = part.GetComponents<ModuleDockingNode>(); if (mdns.Length > 0) { if (topDockModule.model != null) { topDockPartModule = mdns[0]; } if (bottomDockModule.model != null) { bottomDockPartModule = mdns.Length > 1 ? mdns[1] : mdns[0]; } } updateDockingModules(start); } //resources are updated in Start(), to ensure that the dependent modules have loaded }
public override void OnUpdate() { if (!pageActiveState || !JUtil.VesselIsInIVA(vessel)) { return; } currentTarget = FlightGlobals.fetch.VesselTarget; selectedCelestial = currentTarget as CelestialBody; selectedVessel = currentTarget as Vessel; selectedPort = currentTarget as ModuleDockingNode; selectedClaw = currentTarget as ModuleGrappleNode; if (selectedPort != null) { selectedVessel = selectedPort.vessel; } if (selectedClaw != null) { selectedVessel = selectedClaw.vessel; } if (vessel.parts.Count != partCount) { FindReferencePoints(); //UpdateUndockablesList(); } if (!UpdateCheck()) return; UpdateLists(); }
public override void OnStart(PartModule.StartState state) { base.OnStart(state); this.module = base.part.FindModuleImplementing<ModuleDockingNode>(); }
private ModuleDockingHatch GetHatchForDockingNode(ModuleDockingNode dockNode) { IEnumerator<ModuleDockingHatch> epHatches = dockNode.part.Modules.OfType<ModuleDockingHatch>().GetEnumerator(); while (epHatches.MoveNext()) { if (epHatches.Current == null) continue; if (epHatches.Current.modDockNode == dockNode) { return epHatches.Current; } } return null; }
private ModuleDockingHatch GetHatchForDockingNode(ModuleDockingNode dockNode) { foreach (ModuleDockingHatch dockHatch in dockNode.part.Modules.OfType<ModuleDockingHatch>()) { if (dockHatch.modDockNode == dockNode) { return dockHatch; } } return null; }
// Vessel Menu private void TargetVessel(int index, TextMenu.Item ti) { if (selectedVessel == vesselsList[index].vessel) { // Already selected. Are there ports? UpdatePortsList(); if (portsList.Count > 0) { currentMenu = MenuList.Ports; activeMenu = new TextMenu(); activeMenu.rightColumnWidth = 8; activeMenu.labelColor = nameColorTag; activeMenu.selectedColor = selectedColorTag; activeMenu.disabledColor = unavailableColorTag; activeMenu.rightTextColor = distanceColorTag; UpdateLists(); if (selectedPort != null) { int idx = portsList.FindIndex(x => x == selectedPort); activeMenu.currentSelection = idx; } } } else { vesselsList[index].SetTarget(); selectedCelestial = null; selectedPort = null; activeMenu.SetSelected(index, true); } }
private void FetchCommonData() { localGeeASL = vessel.orbit.referenceBody.GeeASL * gee; coM = vessel.findWorldCenterOfMass(); localGeeDirect = FlightGlobals.getGeeForceAtPosition(coM).magnitude; up = (coM - vessel.mainBody.position).normalized; forward = vessel.GetTransform().up; right = vessel.GetTransform().right; north = Vector3d.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - coM).normalized; rotationSurface = Quaternion.LookRotation(north, up); rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface); velocityVesselOrbit = vessel.orbit.GetVel(); velocityVesselSurface = velocityVesselOrbit - vessel.mainBody.getRFrmVel(coM); speedVertical = Vector3d.Dot(velocityVesselSurface, up); speedVerticalRounded = Math.Ceiling(speedVertical * 20) / 20; target = FlightGlobals.fetch.VesselTarget; node = vessel.patchedConicSolver.maneuverNodes.Count > 0 ? vessel.patchedConicSolver.maneuverNodes[0] : null; time = Planetarium.GetUniversalTime(); FetchAltitudes(); terrainHeight = altitudeASL - altitudeTrue; if (time >= lastTimePerSecond + 1) { terrainDelta = terrainHeight - lastTerrainHeight; lastTerrainHeight = terrainHeight; lastTimePerSecond = time; } horzVelocity = (velocityVesselSurface - (speedVertical * up)).magnitude; horzVelocityForward = Vector3d.Dot(velocityVesselSurface, forward); horzVelocityRight = Vector3d.Dot(velocityVesselSurface, right); atmPressure = FlightGlobals.getStaticPressure(altitudeASL, vessel.mainBody); dynamicPressure = 0.5 * velocityVesselSurface.sqrMagnitude * vessel.atmDensity; if (target != null) { targetSeparation = vessel.GetTransform().position - target.GetTransform().position; targetOrientation = target.GetTransform().rotation; targetVessel = target as Vessel; targetBody = target as CelestialBody; targetDockingNode = target as ModuleDockingNode; targetDistance = Vector3.Distance(target.GetTransform().position, vessel.GetTransform().position); // This is kind of messy. targetOrbitSensibility = false; // All celestial bodies except the sun have orbits that make sense. targetOrbitSensibility |= targetBody != null && targetBody != Planetarium.fetch.Sun; if (targetVessel != null) targetOrbitSensibility = JUtil.OrbitMakesSense(targetVessel); if (targetDockingNode != null) targetOrbitSensibility = JUtil.OrbitMakesSense(target.GetVessel()); if (targetOrbitSensibility) targetOrbit = target.GetOrbit(); // TODO: Actually, there's a lot of nonsensical cases here that need more reasonable handling. // Like what if we're targeting a vessel landed on a moon of another planet?... if (targetOrbit != null) { velocityRelativeTarget = vessel.orbit.GetVel() - target.GetOrbit().GetVel(); } else { velocityRelativeTarget = vessel.orbit.GetVel(); } // If our target is somehow our own celestial body, approach speed is equal to vertical speed. if (targetBody == vessel.mainBody) approachSpeed = speedVertical; // In all other cases, that should work. I think. approachSpeed = Vector3d.Dot(velocityRelativeTarget, (target.GetTransform().position - vessel.GetTransform().position).normalized); } else { velocityRelativeTarget = targetSeparation = Vector3d.zero; targetOrbit = null; targetDistance = 0; approachSpeed = 0; targetBody = null; targetVessel = null; targetDockingNode = null; targetOrientation = vessel.GetTransform().rotation; targetOrbitSensibility = false; } orbitSensibility = JUtil.OrbitMakesSense(vessel); if (vessel.situation == Vessel.Situations.SUB_ORBITAL || vessel.situation == Vessel.Situations.FLYING) { // Mental note: the local g taken from vessel.mainBody.GeeASL will suffice. // t = (v+sqrt(v²+2gd))/g or something. // What is the vertical component of current acceleration? double accelUp = Vector3d.Dot(vessel.acceleration, up); double altitude = altitudeTrue; if (vessel.mainBody.ocean && altitudeASL > 0.0) { // AltitudeTrue shows distance above the floor of the ocean, // so use ASL if it's closer in this case, and we're not // already below SL. altitude = Math.Min(altitudeASL, altitudeTrue); } if (accelUp < 0.0 || speedVertical >= 0.0 || Planetarium.TimeScale > 1.0) { // If accelUp is negative, we can't use it in the general // equation for finding time to impact, since it could // make the term inside the sqrt go negative. // If we're going up, we can use this as well, since // the precision is not critical. // If we are warping, accelUp is always zero, so if we // do not use this case, we would fall to the simple // formula, which is wrong. secondsToImpact = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * localGeeASL * altitude)) / localGeeASL; } else if (accelUp > 0.005) { // This general case takes into account vessel acceleration, // so estimates on craft that include parachutes or do // powered descents are more accurate. secondsToImpact = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * accelUp * altitude)) / accelUp; } else { // If accelUp is small, we get floating point precision // errors that tend to make secondsToImpact get really big. secondsToImpact = altitude / -speedVertical; } // MOARdV: I think this gets the computation right. High thrust will // result in NaN, which is already handled. /* double accelerationAtMaxThrust = localG - (totalMaximumThrust / totalShipWetMass); double timeToImpactAtMaxThrust = (speedVertical + Math.Sqrt(speedVertical * speedVertical + 2 * accelerationAtMaxThrust * altitude)) / accelerationAtMaxThrust; bestPossibleSpeedAtImpact = speedVertical - accelerationAtMaxThrust * timeToImpactAtMaxThrust; if (double.IsNaN(bestPossibleSpeedAtImpact)) bestPossibleSpeedAtImpact = 0; */ bestPossibleSpeedAtImpact = SpeedAtImpact(totalMaximumThrust, totalShipWetMass, localGeeASL, speedVertical, altitude); expectedSpeedAtImpact = SpeedAtImpact(totalCurrentThrust, totalShipWetMass, localGeeASL, speedVertical, altitude); } else { secondsToImpact = Double.NaN; bestPossibleSpeedAtImpact = 0; expectedSpeedAtImpact = 0; } }
private static string GetPortName(ModuleDockingNode port) { if (dpaiFound) { PartModule dockingNode = null; for (int i = 0; i < port.part.Modules.Count; i++) { var module = port.part.Modules[i]; if (module.GetType() == dpaiModuleDockingNodeNamed) { dockingNode = module; break; } } if (dockingNode != null) { return (string)dpaiPortName.GetValue(dockingNode); } } return port.part.partInfo.title; }
public void Start() { MonoBehaviour.print("DockPortFix, Start() " + GetHashCode()); if (!HighLogic.LoadedSceneIsFlight) { return; } dockNode = part.GetComponents<ModuleDockingNode>()[portIndex]; dockNodeUndockEvent = dockNode.Events[nameof(dockNode.Undock)]; dockNodeUndockSameEvent = dockNode.Events[nameof(dockNode.UndockSameVessel)]; dockNodeDecoupleEvent = dockNode.Events[nameof(dockNode.Decouple)]; forceUndockEvent = Events[nameof(forceUndock)]; forceUndockEvent.guiName = "Force " + dockNodeUndockEvent.guiName; updateState(); }
// This method allows us to check if a specified ModuleDockingNode is one that this hatch is attached to internal bool IsRelatedDockingNode(ModuleDockingNode dockNode) { if (dockNode.nodeTransformName == this.docNodeTransformName) { this.modDockNode = dockNode; return true; } if (dockNode.referenceAttachNode == this.docNodeAttachmentNodeName) { this.modDockNode = dockNode; return true; } return false; }
private bool CheckForNodeDockedToPart(ModuleDockingNode thisNode, Part otherPart) { bool retVal = false; // TODO remove debugging //Debug.Log("thisNode.dockedPartUId=" + thisNode.dockedPartUId + " otherPart.flightID=" + otherPart.flightID + " thisNode.state:" + thisNode.state); // if (otherPart == thisNode.part.vessel[thisNode.dockedPartUId]) if (thisNode.dockedPartUId == otherPart.flightID) { //Debug.Log("IDs match"); if(thisNode.state == "Docked (dockee)") { //Debug.Log("this module is docked (dockee) to the other part"); retVal = true; } else if (thisNode.state == "Docked (docker)") { //Debug.Log("this module is docked (docker) to the other part"); retVal = true; } else if (thisNode.state == "Acquire") { Debug.LogWarning("this module is in the Acquire state, which might mean it is in the process of docking."); retVal = true; } } return retVal; }
/// <summary> /// Convert the textual docking node state into an enum, so we don't /// need to do string compares. /// </summary> /// <param name="whichNode"></param> /// <returns></returns> internal static DockingNodeState GetNodeState(ModuleDockingNode whichNode) { if (whichNode == null) { return DockingNodeState.UNKNOWN; } switch (whichNode.state) { case "PreAttached": return DockingNodeState.PREATTACHED; case "Docked (docker)": return DockingNodeState.DOCKED; case "Docked (dockee)": return DockingNodeState.DOCKED; case "Ready": return DockingNodeState.READY; default: return DockingNodeState.UNKNOWN; } }
public DockingPortValue(ModuleDockingNode module) : base(module.part) { this.module = module; }
public DockingPortValue(ModuleDockingNode module, SharedObjects sharedObj) : base(module.part, sharedObj) { this.module = module; DockingInitializeSuffixes(); }
public DockingPortValue(global::Part part, ModuleDockingNode module) : base(part) { this.module = module; }
private bool CheckModuleDockingNode() { if (null == this.modDockNode) { // We do not know which ModuleDockingNode we are attached to yet. Try to find one. foreach (ModuleDockingNode dockNode in this.part.Modules.OfType<ModuleDockingNode>()) { if (IsRelatedDockingNode(dockNode)) { this.modDockNode = dockNode; return true; } } } else { return true; } return false; }
public override void OnStart(StartState state) { base.OnStart(state); /*switch (state) { case StartState.Editor: case StartState.None: Logging.PostDebugMessage(this, "Refusing to start when not in flight."); return; default: break; }*/ if (this.ValidSizes != string.Empty) { this.validSizes = new List<string>(); string[] splitSizes = this.ValidSizes.Split(','); for (int idx = 0; idx < splitSizes.Length; idx++) { this.validSizes.Add(splitSizes[idx].Trim()); } this.validSizes.Sort(); this.validSizes.Reverse(); this.defaultSize = this.validSizes[0]; } if (this.validSizes == null || this.validSizes.Count == 0) { Logging.PostDebugMessage(this, "Refusing to start because our module was configured poorly." + "\n\tvalidSizes: {0}", this.validSizes ); return; } Logging.PostDebugMessage(this, "Loaded!" + "\n\tdefaultSize: {0}", this.defaultSize ); this.timeoutTimer = new System.Diagnostics.Stopwatch(); this.dockingModule = this.part.getFirstModuleOfType<ModuleDockingNode>(); if (this.dockingModule == null) { Logging.PostDebugMessage(this, "Failed startup because a docking module could not be found."); return; } this.dockingModule.Fields["nodeType"].isPersistant = true; // If we're not in the editor, not docked, and not preattached, set the current size to the default size. if ( !HighLogic.LoadedSceneIsEditor && this.dockingModule.state != "Docked" && this.dockingModule.state != "PreAttached" ) { this.currentSize = this.defaultSize; } #if DEBUG this.dockingModule.Fields["nodeType"].guiActive = true; this.dockingModule.Fields["nodeType"].guiName = "Node Size"; #endif if (this.dockingModule.referenceAttachNode != string.Empty) { Logging.PostDebugMessage(this, string.Format("referenceAttachNode string: {0}", this.dockingModule.referenceAttachNode)); AttachNode node; for (int nIdx = 0; nIdx < this.part.attachNodes.Count; nIdx++) { node = this.part.attachNodes[nIdx]; if (node.id == this.dockingModule.referenceAttachNode) { this.referenceAttachNode = node; break; } } Logging.PostDebugMessage(this, string.Format("referenceAttachNode: {0}", this.referenceAttachNode)); } this.acquireRangeSqr = this.dockingModule.acquireRange * this.dockingModule.acquireRange; var config = KSP.IO.PluginConfiguration.CreateForType<ModuleAdaptiveDockingNode>(); config.load(); this.vesselFilterDistanceSqr = config.GetValue("vesselFilterDistance", 1000d); config.SetValue("vesselFilterDistance", this.vesselFilterDistanceSqr); this.vesselFilterDistanceSqr *= this.vesselFilterDistanceSqr; config.save(); this.hasAttachedState = !this.hasAttachedPart; Logging.PostDebugMessage(this, "Started!", string.Format("dockingModule: {0}", this.dockingModule) ); }
// Method that can be used to set up the ModuleDockingNode that this ModuleDockingHatch refers to. public void AttachModuleDockingNode(ModuleDockingNode _modDocNode) { this.modDockNode = _modDocNode; this.docNodeTransformName = _modDocNode.nodeTransformName; this.docNodeAttachmentNodeName = _modDocNode.referenceAttachNode; }
private bool CheckModuleDockingNode() { if (null == modDockNode) { // We do not know which ModuleDockingNode we are attached to yet. Try to find one. IEnumerator<ModuleDockingNode> eNodes = part.Modules.OfType<ModuleDockingNode>().GetEnumerator(); while (eNodes.MoveNext()) { if (eNodes.Current == null) continue; if (IsRelatedDockingNode(eNodes.Current)) { modDockNode = eNodes.Current; return true; } } } else { return true; } return false; }
/* * Methods * */ // Runs when each new part is started. public override void OnStart(StartState st) { this.dockingNodeModule = (ModuleDockingNode)base.part.Modules["ModuleDockingNode"]; PartModule needle; for (int idx = 0; idx < base.part.Modules.Count; idx++) { needle = base.part.Modules[idx]; if (needle is ModuleAnimateGeneric) { if (((ModuleAnimateGeneric)needle).animationName == this.deployAnimationControllerName) { this.deployAnimation = (ModuleAnimateGeneric)needle; break; } } } // If we've loaded a deployAnimationControllerName from the cfg... // Start the underlying ModuleDockingNode. base.OnStart(st); ModuleDockingNode prefabModule = PartLoader.getPartInfoByName(this.part.partInfo.name) .partPrefab.getFirstModuleOfType<ModuleDockingNode>(); TweakableTools.InitializeTweakable<ModuleTweakableDockingNode>( this.Fields["acquireRange"].uiControlCurrent(), ref this.acquireRange, ref this.dockingNodeModule.acquireRange, prefabModule.acquireRange ); TweakableTools.InitializeTweakable<ModuleTweakableDockingNode>( this.Fields["acquireForce"].uiControlCurrent(), ref this.acquireForce, ref this.dockingNodeModule.acquireForce, prefabModule.acquireForce ); TweakableTools.InitializeTweakable<ModuleTweakableDockingNode>( this.Fields["acquireTorque"].uiControlCurrent(), ref this.acquireTorque, ref this.dockingNodeModule.acquireTorque, prefabModule.acquireForce ); TweakableTools.InitializeTweakable<ModuleTweakableDockingNode>( this.Fields["undockEjectionForce"].uiControlCurrent(), ref this.undockEjectionForce, ref this.dockingNodeModule.undockEjectionForce, prefabModule.undockEjectionForce ); TweakableTools.InitializeTweakable<ModuleTweakableDockingNode>( this.Fields["minDistanceToReEngage"].uiControlCurrent(), ref this.minDistanceToReEngage, ref this.dockingNodeModule.minDistanceToReEngage, prefabModule.minDistanceToReEngage ); this.Fields["maxRollAngle"].uiControlFlight.controlEnabled = false; this.maxRollAngle = Mathf.Acos(this.minRollDotProduct) * 180f / Mathf.PI; this.dockingNodeModule.acquireMinRollDot = this.minRollDotProduct * this.minRollDotProduct; this.dockingNodeModule.captureMinRollDot = this.minRollDotProduct; this.lastMaxRollAngle = this.maxRollAngle; // If we have a tweakable AttachNode, use it. if (this.TDNnodeName != string.Empty) { this.attachNode = base.part.findAttachNode(this.TDNnodeName); } base.part.attachRules.allowStack = this.IsOpen | this.AlwaysAllowStack; this.dockingNodeModule.Events["EnableXFeed"].guiActive = false; this.dockingNodeModule.Events["DisableXFeed"].guiActive = false; this.dockingNodeModule.Events["EnableXFeed"].guiActiveEditor = false; this.dockingNodeModule.Events["DisableXFeed"].guiActiveEditor = false; this.dockingNodeModule.Events["EnableXFeed"].active = false; this.dockingNodeModule.Events["DisableXFeed"].active = false; /* @subclass ModuleStagingToggle stagingToggleModule; if (this.part.tryGetFirstModuleOfType<ModuleStagingToggle>(out stagingToggleModule)) { stagingToggleModule.OnToggle += new ModuleStagingToggle.ToggleEventHandler(this.OnStagingToggle); } */ // Yay debugging! this.LogDebug( "{0}: Started with assembly version {4}." + "\n\tdeployAnimationModule={1}, attachNode={2}, TDNnodeName={3}, attachedPart={5}, fuelCrossFeed={6}", this.GetType().Name, this.deployAnimation, this.attachNode, this.TDNnodeName, this.GetType().Assembly.GetName().Version, this.attachedPart ); }
/// <summary> /// Refresh docking node data, including selecting the "reference" /// docking node (for docking node control). /// </summary> private void FetchDockingNodeData() { mainDockingNode = null; mainDockingNodeState = DockingNodeState.UNKNOWN; Part referencePart = vessel.GetReferenceTransformPart(); if (referencePart != null) { ModuleDockingNode node = referencePart.FindModuleImplementing<ModuleDockingNode>(); if (node != null) { // The current reference part is a docking node, so we // choose it. mainDockingNode = node; } } if (mainDockingNode == null) { uint launchId; Part currentPart = JUtil.DeduceCurrentPart(vessel); if (currentPart == null) { launchId = 0u; } else { launchId = currentPart.launchID; } for (int i = 0; i < vessel.parts.Count; ++i) { if (vessel.parts[i].launchID == launchId) { ModuleDockingNode node = vessel.parts[i].FindModuleImplementing<ModuleDockingNode>(); if (node != null) { // We found a docking node that has the same launch // ID as the current IVA part, so we consider it our // main docking node. mainDockingNode = node; break; } } } } mainDockingNodeState = GetNodeState(mainDockingNode); }