public static string GetGreatestCommonNodeType(ModuleAdaptiveDockingNode n1, ModuleAdaptiveDockingNode n2) { int count1 = 0; int count2 = 0; while (count1 < n1.validSizes.Count && count2 < n2.validSizes.Count) { int compareResult; compareResult = n1.validSizes[count1].CompareTo(n2.validSizes[count2]); if (compareResult == 0) { return(n1.validSizes[count1]); } else if (compareResult > 0) { count1++; } else { count2++; } } return(string.Empty); }
public void LateUpdate() { if (HighLogic.LoadedSceneIsEditor) { Logging.PostDebugMessage(this, "LateUpdate", string.Format("attachedPart: {0}", this.attachedPart)); if (this.hasAttachedPart != this.hasAttachedState) { this.hasAttachedState = this.hasAttachedPart; if (this.attachedPart != null) { ModuleDockingNode attachedNode = this.attachedPart.getFirstModuleOfType <ModuleDockingNode>(); Logging.PostDebugMessage(this, string.Format("attachedNode: {0}", attachedNode)); if (attachedNode != null) { ModuleAdaptiveDockingNode attachedADN = this.attachedPart .getFirstModuleOfType <ModuleAdaptiveDockingNode>(); if (attachedADN != null && attachedADN.currentSize != this.currentSize) { this.currentSize = GetGreatestCommonNodeType(this, attachedADN); Logging.PostDebugMessage(this, string.Format("Attached to AdaptiveDockingNode, setting currentSize = {0}", this.currentSize) ); } else if (attachedNode.nodeType != this.currentSize) { this.currentSize = attachedNode.nodeType; Logging.PostDebugMessage(this, string.Format("Attached to ModuleDockingNode, setting currentSize = {0}", this.currentSize) ); } } } } } }
public void FixedUpdate() { if ( HighLogic.LoadedSceneIsFlight && FlightGlobals.Vessels != null && this.vessel != null && this.dockingModule != null ) { #if DEBUG bool foundApproach = false; #endif PooledDebugLogger verboseLog = PooledDebugLogger.New(this); #if DEBUG try { #endif verboseLog.AppendFormat(" ({0}_{1}) on {2}", this.part.partInfo.name, this.part.craftID, this.vessel.vesselName); verboseLog.AppendFormat("\nChecking within acquireRangeSqr: {0}", this.acquireRangeSqr); verboseLog.AppendFormat("this.dockingModule: {0}\n", this.dockingModule == null ? "null" : this.dockingModule.ToString()); verboseLog.AppendFormat("this.dockingModule.state: {0}\n", this.dockingModule == null || this.dockingModule.state == null ? "null" :this.dockingModule.state.ToString()); // If we're already docked or pre-attached... if (this.dockingModule.state == "Docked" || this.dockingModule.state == "PreAttached") { // ...and if the timeout timer is running... if (this.timeoutTimer.IsRunning) { // ...reset the timeout timer this.timeoutTimer.Reset(); } // ...skip this check return; } // If the timeout timer is running, we found a match recently. If we haven't found a match in more than // five seconds, it's not recent anymore, so reset our size to default. if (this.timeoutTimer.IsRunning && this.timeoutTimer.ElapsedMilliseconds > 5000) { verboseLog.AppendFormat("\nNo target detected within 5 seconds, timing out."); if (this.dockingModule.state != "Docked") { verboseLog.AppendFormat("\nReverting to default nodeType: {0}", this.defaultSize); this.currentSize = this.defaultSize; } this.timeoutTimer.Reset(); } bool foundTargetNode = false; float closestNodeDistSqr = this.acquireRangeSqr * 4f; verboseLog.Append("Starting Vessels loop."); // Check all vessels for potential docking targets Vessel vessel; for (int vIdx = 0; vIdx < FlightGlobals.Vessels.Count; vIdx++) { vessel = FlightGlobals.Vessels[vIdx]; if (vessel == null) { verboseLog.Append("Skipping null vessel."); continue; } // Skip vessels that are just way too far away. if (this.vessel.sqrDistanceTo(vessel) > this.vesselFilterDistanceSqr) { verboseLog.AppendFormat("\nSkipping distant vessel {0} (sqrDistance {1})", vessel.vesselName, (vessel.GetWorldPos3D() - this.dockingModule.nodeTransform.position).sqrMagnitude ); continue; } verboseLog.AppendFormat("\nChecking nearby vessel {0} (sqrDistance {1})", vessel.vesselName, (vessel.GetWorldPos3D() - this.dockingModule.nodeTransform.position).sqrMagnitude ); // Since this vessel is not too far away, check all docking nodes on the vessel. IList <ModuleDockingNode> potentialNodes = vessel.getModulesOfType <ModuleDockingNode>(); ModuleDockingNode potentialTargetNode; for (int nIdx = 0; nIdx < potentialNodes.Count; nIdx++) { potentialTargetNode = potentialNodes[nIdx]; if (potentialTargetNode == null) { verboseLog.AppendFormat("\nSkipping potentialTargetNode at index {0} because it is null", nIdx); continue; } if (potentialTargetNode.part == null) { verboseLog.AppendFormat("\nSkipping potentialTargetNode at index {0} because its part is null", nIdx); continue; } if (potentialTargetNode.nodeTransform == null) { verboseLog.AppendFormat("\nSkipping potentialTargetNode at index {0} because its node transform is null", nIdx); continue; } verboseLog.AppendFormat("\nFound potentialTargetNode: {0}", potentialTargetNode); verboseLog.AppendFormat("\n\tpotentialTargetNode.state: {0}", potentialTargetNode.state); verboseLog.AppendFormat("\n\tpotentialTargetNode.nodeType: {0}", potentialTargetNode.nodeType); // We can't skip the current vessel, because it's possible to dock parts on a single vessel to // each other. Still, we can't dock a port to itself, so skip this part. if (potentialTargetNode.part == this.part) { verboseLog.AppendFormat("\nDiscarding potentialTargetNode: on this part."); continue; } // If this docking node is already docked, we can't dock to it, so skip it. if ( potentialTargetNode.state.Contains("Docked") || potentialTargetNode.state.Contains("PreAttached")) { verboseLog.Append("\nDiscarding potentialTargetNode: not ready."); continue; } float thisNodeDistSqr = (potentialTargetNode.nodeTransform.position - this.dockingModule.nodeTransform.position) .sqrMagnitude; verboseLog.AppendFormat( "\n\tChecking potentialTargetNode sqrDistance against the lesser of acquireRangeSqr and " + "closestNodeDistSqr ({0})", Mathf.Min(this.acquireRangeSqr * 4f, closestNodeDistSqr) ); // Only bother checking nodes closer than twice our acquire range. We have to check before we // get within acquire range to make sure Squad's code will catch us when we get there. if (thisNodeDistSqr <= Mathf.Min(this.acquireRangeSqr * 4f, closestNodeDistSqr)) { #if DEBUG foundApproach = true; #endif verboseLog.AppendFormat( "\n\tpotentialTargetNode is nearby ({0}), checking if adaptive.", thisNodeDistSqr); ModuleAdaptiveDockingNode targetAdaptiveNode = null; string targetSize; targetSize = string.Empty; // adapt to non-adaptive docking nodes if (this.validSizes.Contains(potentialTargetNode.nodeType)) { targetSize = potentialTargetNode.nodeType; this.currentSize = targetSize; } // Otherwise, look for another adaptive node. else { // Check the part for an AdaptiveDockingNode targetAdaptiveNode = potentialTargetNode.part .getFirstModuleOfType <ModuleAdaptiveDockingNode>(); } // If we've found an AdaptiveDockingNode... if (targetAdaptiveNode != null) { verboseLog.AppendFormat("\n\tpotentialTargetNode is adaptive."); verboseLog.AppendFormat("\n\tdefaultSize: {0}", targetAdaptiveNode.defaultSize); verboseLog.AppendFormat("\n\tvalidSizes: {0}", targetAdaptiveNode.validSizes); // ...and if we can become its largest (default) size... // to their default size. if (this.validSizes.Contains(targetAdaptiveNode.defaultSize)) { // ...target its default size. targetSize = targetAdaptiveNode.defaultSize; } // ...otherwise, look for a common size. else { string commonNodeType = GetGreatestCommonNodeType(this, targetAdaptiveNode); // ...if we didn't find a common size, stop processing this node if (commonNodeType == string.Empty) { verboseLog.AppendFormat("\n\tInvalid adaptive target: no common node types."); continue; } targetSize = commonNodeType; targetAdaptiveNode.currentSize = targetSize; verboseLog.AppendFormat( "\n\tTarget nodeType set to commonNodeType: {0}", targetSize); } } #if DEBUG else { verboseLog.AppendFormat("\n\tpotentialTargetNode is not adaptive."); verboseLog.AppendFormat("\n\tnodeType: {0}", potentialTargetNode.nodeType); } #endif // If we never found a target size, it's not a match, so stop processing. if (targetSize == string.Empty) { continue; } // ...otherwise, log this node as the closest and adapt to the target size. closestNodeDistSqr = thisNodeDistSqr; this.currentSize = targetSize; foundTargetNode = true; verboseLog.AppendFormat("\n\tLocal nodeType set to commonNodeType: {0}", targetSize); verboseLog.AppendFormat("\n\tFound suitable docking node."); verboseLog.AppendFormat("\n\ttargetSize: {0}", targetSize); verboseLog.AppendFormat("\n\tForward vector dot product: {0} (acquire minimum: {1})", Vector3.Dot(potentialTargetNode.nodeTransform.forward, this.dockingModule.nodeTransform.forward), this.dockingModule.acquireMinFwdDot ); verboseLog.AppendFormat("\n\tUp vector dot product: {0} (acquire minimum: {1})", Vector3.Dot(potentialTargetNode.nodeTransform.up, this.dockingModule.nodeTransform.up), this.dockingModule.acquireMinRollDot ); } else { verboseLog.AppendFormat( "\nDiscarding potentialTargetNode: too far away (thisNodeDistSqr: {0})", thisNodeDistSqr ); } } verboseLog.Append('\n'); } verboseLog.Append("\nFixedUpdate Finished."); if (foundTargetNode) { if (this.timeoutTimer.IsRunning) { this.timeoutTimer.Reset(); } this.timeoutTimer.Start(); } #if DEBUG } finally { // if (foundApproach) verboseLog.Print(); } #endif } }
public static string GetGreatestCommonNodeType(ModuleAdaptiveDockingNode n1, ModuleAdaptiveDockingNode n2) { int count1 = 0; int count2 = 0; while (count1 < n1.validSizes.Count && count2 < n2.validSizes.Count) { int compareResult; compareResult = n1.validSizes[count1].CompareTo(n2.validSizes[count2]); if (compareResult == 0) { return n1.validSizes[count1]; } else if (compareResult > 0) { count1++; } else { count2++; } } return string.Empty; }