Enable Activate & Deactive events from EVA.
Enable Activate & Deactive events from EVA.

--- a/CoreStrut.cs
+++ b/CoreStrut.cs
@@ -9,8 +9,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-
-//using System.Threading.Tasks;
 using UnityEngine;
 
 namespace QuantumStrut

--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -1,37 +1,37 @@
-using System.Reflection;

-using System.Runtime.CompilerServices;

-using System.Runtime.InteropServices;

-

-// General Information about an assembly is controlled through the following 

-// set of attributes. Change these attribute values to modify the information

-// associated with an assembly.

-[assembly: AssemblyTitle("AutoStrut")]

-[assembly: AssemblyDescription("")]

-[assembly: AssemblyConfiguration("")]

-[assembly: AssemblyCompany("")]

-[assembly: AssemblyProduct("AutoStrut")]

-[assembly: AssemblyCopyright("Copyright ©  2012")]

-[assembly: AssemblyTrademark("")]

-[assembly: AssemblyCulture("")]

-

-// Setting ComVisible to false makes the types in this assembly not visible 

-// to COM components.  If you need to access a type in this assembly from 

-// COM, set the ComVisible attribute to true on that type.

-[assembly: ComVisible(false)]

-

-// The following GUID is for the ID of the typelib if this project is exposed to COM

-[assembly: Guid("57e209db-4b94-46b4-be0e-bd6e830d4eb5")]

-

-// Version information for an assembly consists of the following four values:

-//

-//      Major Version

-//      Minor Version 

-//      Build Number

-//      Revision

-//

-// You can specify all the values or you can default the Build and Revision Numbers 

-// by using the '*' as shown below:

-// [assembly: AssemblyVersion("1.0.*")]

-[assembly: AssemblyVersion("1.0.0.0")]

-[assembly: AssemblyFileVersion("1.0.0.0")]

+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("QuantumStrutsContinued")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("QuantumStrutsContinued")]
+[assembly: AssemblyCopyright("Copyright © 2014 toadicus")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("57e209db-4b94-46b4-be0e-bd6e830d4eb5")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+

--- a/QuantumStrut.cs
+++ b/QuantumStrut.cs
@@ -9,8 +9,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-
-//using System.Threading.Tasks;
 using UnityEngine;
 
 namespace QuantumStrut
@@ -76,14 +74,14 @@
 
 		#region Events
 
-		[KSPEvent(guiActive = true, guiName = "Activate", active = true)]
+		[KSPEvent(guiActive = true, guiName = "Activate", active = true, guiActiveUnfocused = true, unfocusedRange = 2f)]
 		public void ActivateStrut()
 		{
 			IsEnabled = true;
 			CheckHit();
 		}
 
-		[KSPEvent(guiActive = true, guiName = "Deactivate", active = false)]
+		[KSPEvent(guiActive = true, guiName = "Deactivate", active = false, guiActiveUnfocused = true, unfocusedRange = 2f)]
 		public void DeactivateStrut()
 		{
 			IsEnabled = false;
@@ -197,9 +195,9 @@
 				if (strut != null && !strut.isDestroyed)
 				{
 					if (PowerConsumption == 0 || (Util.GetEnergy(part.vessel) > PowerConsumption * TimeWarp.fixedDeltaTime && part.RequestResource(
-						                   "ElectricCharge",
-						                   PowerConsumption * TimeWarp.fixedDeltaTime
-					                   ) > 0))
+						    "ElectricCharge",
+						    PowerConsumption * TimeWarp.fixedDeltaTime
+					    ) > 0))
 						strut.Update();
 					else
 						strut.Destroy();

--- a/QuantumStrutCore.cs
+++ b/QuantumStrutCore.cs
@@ -10,470 +10,490 @@
 using System.ComponentModel;
 using System.Linq;
 using System.Text;
-//using System.Threading.Tasks;
 using UnityEngine;
 using KSP.IO;
 
-
 namespace QuantumStrut
 {
-    class QuantumStrutCore : PartModule
-    {
-        GameObject lineObj = null;
-        LineRenderer lr = null;
-        ConfigNode nodeToLoad = null;
-
-        bool Placing = false;
-        bool Deleting = false;
-        List<CoreStrut> struts = new List<CoreStrut>();
-
-        Part startPart = null;
-        Vector3 startOffset = Vector3.zero;
-        Part endPart = null;
-        Vector3 endOffset = Vector3.zero;
-
-        public Material material = null;
-        public Color startColor = Color.white;
-        public Color endColor = Color.white;
-
-        #region Fields
-        [KSPField(isPersistant = true)]
-        public bool IsEnabled = true;
-
-        [KSPField(isPersistant = false)]
-        public float PowerConsumption = 0;
-
-        [KSPField(isPersistant = false)]
-        public int MaxStruts = 8;
-
-        [KSPField(isPersistant = false)]
-        public string Material = "Particles/Additive";
-
-        [KSPField(isPersistant = false)]
-        public Vector3 StartColor = Vector3.zero;
-
-        [KSPField(isPersistant = false)]
-        public Vector3 EndColor = Vector3.zero;
-
-
-        [KSPField(isPersistant = false)]
-        public float StartSize = 0.03f;
-
-        [KSPField(isPersistant = false)]
-        public float EndSize = 0.0075f;
-        #endregion
-
-        #region Actions
-        [KSPAction("Toggle")]
-        public void ToggleCore(KSPActionParam param)
-        {
-            IsEnabled = !IsEnabled;
-        }
-
-        [KSPAction("Activate")]
-        public void ActivateCore(KSPActionParam param)
-        {
-            IsEnabled = true;
-        }
-
-        [KSPAction("Deactivate")]
-        public void DeactivateCore(KSPActionParam param)
-        {
-            IsEnabled = false;
-        }
-        #endregion
-
-        #region Events
-        [KSPEvent(guiActive = true, guiName = "Place Strut", active = false, externalToEVAOnly=true, guiActiveUnfocused=true, unfocusedRange = 5)]
-        public void BeginPlace()
-        {
-            startPart = null;
-            startOffset = Vector3.zero;
-            endPart = null;
-            endOffset = Vector3.zero;
-            Placing = true;
-        }
-
-        [KSPEvent(guiActive = true, guiName = "Remove Strut", active = false, externalToEVAOnly = true, guiActiveUnfocused = true, unfocusedRange = 2500)]
-        public void BeginDelete()
-        {
-            Deleting = true;
-        }
-
-        [KSPEvent(guiActive = true, guiName = "Activate", active = true)]
-        public void ActivateCore()
-        {
-            IsEnabled = true;
-        }
-
-        [KSPEvent(guiActive = true, guiName = "Deactivate", active = false)]
-        public void DeactivateCore()
-        {
-            IsEnabled = false;
-        }
-        #endregion
-
-        public Vector3 StringToVector3(string str)
-        {
-            string[] vals = str.Split(',');
-            float x = (float)Convert.ToDecimal(vals[0]);
-            float y = (float)Convert.ToDecimal(vals[1]);
-            float z = (float)Convert.ToDecimal(vals[2]);
-            return new Vector3(x, y, z);
-        }
-
-        public Color Vector3toColor(Vector3 vec)
-        {
-            return new Color(vec.x / 255, vec.y / 255, vec.z / 255);
-        }
-
-        Part partFromGameObject(GameObject ob)
-        {
-            GameObject o = ob;
-
-            while (o)
-            {
-                Part p = Part.FromGO(o);
-                if (p && p != null)
-                {
-                    return p;
-                }
-
-                if (o.transform.parent)
-                    o = o.transform.parent.gameObject;
-                else
-                    return null;
-            }
-            return null;
-        }
-
-        Part partFromRaycast(RaycastHit hit)
-        {
-            return partFromGameObject(hit.collider.gameObject);
-        }
-
-        Part partFromId(long id)
-        {
-            Console.WriteLine("Vessel Parts: " + part.vessel.Parts.Count);
-            foreach (Part p in part.vessel.Parts)
-            {
-                print(p.uid + " ?= " + id + ": " + (p.uid == id));
-                if (p.uid == id)
-                    return p;
-            }
-            return null;
-        }
-
-        bool isValid(UnityEngine.Object obj)
-        {
-            return (obj && obj != null);
-        }
-
-        void InitLaser()
-        {
-            if (!isValid(lr))
-            {
-                lineObj = new GameObject();
-
-                lr = lineObj.AddComponent<LineRenderer>();
-                lr.useWorldSpace = true;
-
-                lr.material = new Material(Shader.Find("Particles/Additive"));
-                lr.SetColors(Color.white, Color.white);
-                lr.SetWidth(0.03f, 0.03f);
-
-                lr.SetVertexCount(2);
-                lr.SetPosition(0, Vector3.zero);
-                lr.SetPosition(1, Vector3.zero);
-                lr.castShadows = false;
-                lr.receiveShadows = true;
-            }
-        }
-
-        void DestroyLaser()
-        {
-            if (isValid(lr))
-                LineRenderer.DestroyImmediate(lr);
-            if (isValid(lineObj))
-                GameObject.DestroyImmediate(lineObj);
-        }
-
-        float GetEnergy()
-        {
-            double energy = 0;
-            foreach (Part p in part.vessel.parts)
-            {
-                foreach (PartResource r in p.Resources)
-                {
-                    if (r.resourceName == "ElectricCharge")
-                        energy += r.amount;
-                }
-            }
-            return (float)energy;
-        }
-
-        void AddStrut(Part a, Vector3 aO, Part b, Vector3 bO)
-        {
-            CoreStrut s = new CoreStrut(a, aO, b, bO);
-            s.Material = material;
-            s.StartColor = startColor;
-            s.EndColor = endColor;
-            s.StartSize = StartSize;
-            s.EndSize = EndSize;
-            struts.Add(s);
-        }
-
-        public override string GetInfo()
-        {
-            return "Max Struts: " + MaxStruts + "\nRequires:\n- ElectricCharge (" + PowerConsumption + "/s.)\n\n Energy cost is per-strut.";
-        }
-
-        public override void OnStart(PartModule.StartState state)
-        {
-            try
-            {
-                material = new Material(Shader.Find(Material.Trim()));
-            }
-            catch
-            {
-                material = null;
-            }
-
-            startColor = Vector3toColor(StartColor);
-            endColor = Vector3toColor(EndColor);
-            base.OnStart(state);
-        }
-
-        public override void OnSave(ConfigNode node)
-        {
-            foreach (CoreStrut strut in struts)
-            {
-                if (!strut.isDestroyed)
-                {
-                    ConfigNode n = node.AddNode("QuantumStrut");
-                    n.AddValue("parent", part.vessel.parts.IndexOf(strut.parent));
-                    n.AddValue("parentOffset", strut.parentOffset.x + "," + strut.parentOffset.y + "," + strut.parentOffset.z);
-                    n.AddValue("target", part.vessel.parts.IndexOf(strut.target));
-                    n.AddValue("targetOffset", strut.targetOffset.x + "," + strut.targetOffset.y + "," + strut.targetOffset.z);
-                }
-            }
-
-            base.OnSave(node);
-        }
-
-        public override void OnLoad(ConfigNode node)
-        {
-            if (nodeToLoad == null)
-                nodeToLoad = node;
-
-            base.OnLoad(node);
-        }
-
-        void printObj(object obj)
-        {
-            using (KSP.IO.TextWriter writer = TextWriter.CreateForType<string>("obj.cs"))
-            {
-                string str = printProperties(obj, TypeDescriptor.GetProperties(obj), 0);
-                writer.Write(str);
-                print(str);
-            }
-        }
-
-        string printProperties(object obj, PropertyDescriptorCollection collection, int I)
-        {
-            if (I > 2) return "";
-
-            string prefix = "";
-            string str = "";
-            for (int T = 0; T < I; T++)
-            {
-                prefix += "    ";
-            }
-
-            str += "\n" + prefix + "#region";
-            foreach (PropertyDescriptor d in collection)
-            {
-                str += "\n" + prefix + d.Name + " = " + d.GetValue(obj);
-                str += printProperties(obj, d.GetChildProperties(obj), I+1);
-            }
-            str += "\n" + prefix + "#endregion";
-            return str;
-        }
-
-        public override void OnUpdate()
-        {
-            bool eva = isValid(Util.Kerbal);
-            Events["ActivateCore"].active = !IsEnabled;
-            Events["DeactivateCore"].active = IsEnabled;
-            Events["BeginPlace"].active = !Placing && !Deleting && struts.Count < MaxStruts && eva;
-            Events["BeginDelete"].active = !Deleting && !Placing && struts.Count > 0 && eva;
-
-            if (nodeToLoad != null)
-            {
-                foreach (ConfigNode strut in nodeToLoad.GetNodes("QuantumStrut"))
-                {
-                    Part parent = part.vessel.parts[Convert.ToInt32(strut.GetValue("parent"))];
-                    Vector3 parentOffset = StringToVector3(strut.GetValue("parentOffset"));
-                    Part target = part.vessel.parts[Convert.ToInt32(strut.GetValue("target"))];
-                    Vector3 targetOffset = StringToVector3(strut.GetValue("targetOffset"));
-
-                    if (isValid(parent) && isValid(target))
-                        AddStrut(parent, parentOffset, target, targetOffset);
-                }
-                nodeToLoad = null;
-            }
-
-            if (eva)
-            {
-                InitLaser();
-                if (Placing)
-                {
-                    RaycastHit info = new RaycastHit();
-                    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
-                    bool hit = Physics.Raycast(ray, out info, Mathf.Infinity);
-                    if (isValid(startPart))
-                    {
-                        Vector3 pos = startPart.transform.TransformPoint(startOffset);
-                        ray = new Ray(pos, (info.point - pos).normalized);
-                        hit = Physics.Raycast(ray, out info, 10);
-                    }
-
-                    if (Input.GetMouseButtonUp(0))
-                    {
-                        if (hit)
-                        {
-                            if (!isValid(startPart))
-                            {
-                                startPart = partFromRaycast(info);
-                                if (isValid(startPart))
-                                    startOffset = startPart.transform.InverseTransformPoint(info.point);
-                            }
-                            else if (!isValid(endPart))
-                            {
-                                Part p = partFromRaycast(info);
-                                if (isValid(p))
-                                {
-                                    if (p != startPart && startPart.vessel.parts.Contains(p))
-                                    {
-                                        endPart = p;
-                                        endOffset = endPart.transform.InverseTransformPoint(info.point);
-
-                                        AddStrut(startPart, startOffset, endPart, endOffset);
-                                    }
-                                    Placing = false;
-                                }
-                            }
-                        }
-                    }
-
-                    if(isValid(startPart))
-                    {
-                        if (hit)
-                        {
-                            Part p = partFromRaycast(info);
-                            Color c = Color.red;
-
-                            if (isValid(p))
-                            {
-                                if (startPart.vessel.parts.Contains(p) && p != startPart)
-                                    c = Color.green;
-                            }
-
-                            lr.SetColors(c, c);
-                            lr.SetPosition(0, startPart.transform.TransformPoint(startOffset));
-                            lr.SetPosition(1, info.point);
-                        }
-                        else
-                        {
-                            lr.SetColors(Color.red, Color.red);
-                            lr.SetPosition(0, startPart.transform.TransformPoint(startOffset));
-                            lr.SetPosition(1, ray.GetPoint(10));
-                        }
-                    }
-                }
-                else
-                {
-                    lr.SetPosition(0, Vector3.zero);
-                    lr.SetPosition(1, Vector3.zero);
-                }
-
-                if (Deleting)
-                {
-                    RaycastHit info = new RaycastHit();
-                    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
-                    bool hit = Physics.Raycast(ray, out info, Mathf.Infinity);
-
-                    CoreStrut closest = null;
-                    float closestDist = Mathf.Infinity;
-                    foreach (CoreStrut strut in struts)
-                    {
-                        strut.Selected = false;
-                        if (hit)
-                        {
-                            Vector3 start = strut.parent.transform.TransformPoint(strut.parentOffset);
-                            float d = Vector3.Distance(start, info.point);
-
-                            if (d < 0.05 && d < closestDist)
-                            {
-                                closest = strut;
-                                closestDist = d;
-                            }
-                        }
-                    }
-
-                    if(closest != null)
-                        closest.Selected = true;
-
-                    if (Input.GetMouseButtonUp(0))
-                    {
-                        if (closest != null)
-                        {
-                            closest.Destroy();
-                            struts.Remove(closest);
-                        }
-                        Deleting = false;
-                    }
-                }
-            }
-            else
-            {
-                DestroyLaser();
-            }
-
-            foreach (CoreStrut s in struts.ToArray())
-            {
-                if (IsEnabled)
-                {
-                    if (s.Active)
-                    {
-                        if (PowerConsumption == 0 || (GetEnergy() > PowerConsumption * TimeWarp.fixedDeltaTime && part.RequestResource("ElectricCharge", PowerConsumption * TimeWarp.fixedDeltaTime) > 0))
-                        {
-                            s.Active = true;
-                        }
-                        else
-                        {
-                            s.Active = false;
-                        }
-                    }
-                    else
-                    {
-                        if (GetEnergy() > 5 * TimeWarp.fixedDeltaTime && part.RequestResource("ElectricCharge", 5 * TimeWarp.fixedDeltaTime) > 0)
-                        {
-                            s.Active = true;
-                        }
-                    }
-                }
-                else
-                {
-                    s.Active = false;
-                }
-
-                s.Update();
-                if (s.isDestroyed)
-                    struts.Remove(s);
-            }
-            base.OnUpdate();
-        }
-    }
+	class QuantumStrutCore : PartModule
+	{
+		GameObject lineObj = null;
+		LineRenderer lr = null;
+		ConfigNode nodeToLoad = null;
+		bool Placing = false;
+		bool Deleting = false;
+		List<CoreStrut> struts = new List<CoreStrut>();
+		Part startPart = null;
+		Vector3 startOffset = Vector3.zero;
+		Part endPart = null;
+		Vector3 endOffset = Vector3.zero;
+		public Material material = null;
+		public Color startColor = Color.white;
+		public Color endColor = Color.white;
+
+		#region Fields
+
+		[KSPField(isPersistant = true)]
+		public bool IsEnabled = true;
+		[KSPField(isPersistant = false)]
+		public float PowerConsumption = 0;
+		[KSPField(isPersistant = false)]
+		public int MaxStruts = 8;
+		[KSPField(isPersistant = false)]
+		public string Material = "Particles/Additive";
+		[KSPField(isPersistant = false)]
+		public Vector3 StartColor = Vector3.zero;
+		[KSPField(isPersistant = false)]
+		public Vector3 EndColor = Vector3.zero;
+		[KSPField(isPersistant = false)]
+		public float StartSize = 0.03f;
+		[KSPField(isPersistant = false)]
+		public float EndSize = 0.0075f;
+
+		#endregion
+
+		#region Actions
+
+		[KSPAction("Toggle")]
+		public void ToggleCore(KSPActionParam param)
+		{
+			IsEnabled = !IsEnabled;
+		}
+
+		[KSPAction("Activate")]
+		public void ActivateCore(KSPActionParam param)
+		{
+			IsEnabled = true;
+		}
+
+		[KSPAction("Deactivate")]
+		public void DeactivateCore(KSPActionParam param)
+		{
+			IsEnabled = false;
+		}
+
+		#endregion
+
+		#region Events
+
+		[KSPEvent(
+			guiActive = true,
+			guiName = "Place Strut",
+			active = false,
+			externalToEVAOnly = true,
+			guiActiveUnfocused = true,
+			unfocusedRange = 5
+		)]
+		public void BeginPlace()
+		{
+			startPart = null;
+			startOffset = Vector3.zero;
+			endPart = null;
+			endOffset = Vector3.zero;
+			Placing = true;
+		}
+
+		[KSPEvent(
+			guiActive = true,
+			guiName = "Remove Strut",
+			active = false,
+			externalToEVAOnly = true,
+			guiActiveUnfocused = true,
+			unfocusedRange = 2500
+		)]
+		public void BeginDelete()
+		{
+			Deleting = true;
+		}
+
+		[KSPEvent(guiActive = true, guiName = "Activate", active = true)]
+		public void ActivateCore()
+		{
+			IsEnabled = true;
+		}
+
+		[KSPEvent(guiActive = true, guiName = "Deactivate", active = false)]
+		public void DeactivateCore()
+		{
+			IsEnabled = false;
+		}
+
+		#endregion
+
+		public Vector3 StringToVector3(string str)
+		{
+			string[] vals = str.Split(',');
+			float x = (float)Convert.ToDecimal(vals[0]);
+			float y = (float)Convert.ToDecimal(vals[1]);
+			float z = (float)Convert.ToDecimal(vals[2]);
+			return new Vector3(x, y, z);
+		}
+
+		public Color Vector3toColor(Vector3 vec)
+		{
+			return new Color(vec.x / 255, vec.y / 255, vec.z / 255);
+		}
+
+		Part partFromGameObject(GameObject ob)
+		{
+			GameObject o = ob;
+
+			while (o)
+			{
+				Part p = Part.FromGO(o);
+				if (p && p != null)
+				{
+					return p;
+				}
+
+				if (o.transform.parent)
+					o = o.transform.parent.gameObject;
+				else
+					return null;
+			}
+			return null;
+		}
+
+		Part partFromRaycast(RaycastHit hit)
+		{
+			return partFromGameObject(hit.collider.gameObject);
+		}
+
+		Part partFromId(long id)
+		{
+			Console.WriteLine("Vessel Parts: " + part.vessel.Parts.Count);
+			foreach (Part p in part.vessel.Parts)
+			{
+				print(p.uid + " ?= " + id + ": " + (p.uid == id));
+				if (p.uid == id)
+					return p;
+			}
+			return null;
+		}
+
+		bool isValid(UnityEngine.Object obj)
+		{
+			return (obj && obj != null);
+		}
+
+		void InitLaser()
+		{
+			if (!isValid(lr))
+			{
+				lineObj = new GameObject();
+
+				lr = lineObj.AddComponent<LineRenderer>();
+				lr.useWorldSpace = true;
+
+				lr.material = new Material(Shader.Find("Particles/Additive"));
+				lr.SetColors(Color.white, Color.white);
+				lr.SetWidth(0.03f, 0.03f);
+
+				lr.SetVertexCount(2);
+				lr.SetPosition(0, Vector3.zero);
+				lr.SetPosition(1, Vector3.zero);
+				lr.castShadows = false;
+				lr.receiveShadows = true;
+			}
+		}
+
+		void DestroyLaser()
+		{
+			if (isValid(lr))
+				LineRenderer.DestroyImmediate(lr);
+			if (isValid(lineObj))
+				GameObject.DestroyImmediate(lineObj);
+		}
+
+		float GetEnergy()
+		{
+			double energy = 0;
+			foreach (Part p in part.vessel.parts)
+			{
+				foreach (PartResource r in p.Resources)
+				{
+					if (r.resourceName == "ElectricCharge")
+						energy += r.amount;
+				}
+			}
+			return (float)energy;
+		}
+
+		void AddStrut(Part a, Vector3 aO, Part b, Vector3 bO)
+		{
+			CoreStrut s = new CoreStrut(a, aO, b, bO);
+			s.Material = material;
+			s.StartColor = startColor;
+			s.EndColor = endColor;
+			s.StartSize = StartSize;
+			s.EndSize = EndSize;
+			struts.Add(s);
+		}
+
+		public override string GetInfo()
+		{
+			return "Max Struts: " + MaxStruts + "\nRequires:\n- ElectricCharge (" + PowerConsumption + "/s.)\n\n Energy cost is per-strut.";
+		}
+
+		public override void OnStart(PartModule.StartState state)
+		{
+			try
+			{
+				material = new Material(Shader.Find(Material.Trim()));
+			}
+			catch
+			{
+				material = null;
+			}
+
+			startColor = Vector3toColor(StartColor);
+			endColor = Vector3toColor(EndColor);
+			base.OnStart(state);
+		}
+
+		public override void OnSave(ConfigNode node)
+		{
+			foreach (CoreStrut strut in struts)
+			{
+				if (!strut.isDestroyed)
+				{
+					ConfigNode n = node.AddNode("QuantumStrut");
+					n.AddValue("parent", part.vessel.parts.IndexOf(strut.parent));
+					n.AddValue(
+						"parentOffset",
+						strut.parentOffset.x + "," + strut.parentOffset.y + "," + strut.parentOffset.z
+					);
+					n.AddValue("target", part.vessel.parts.IndexOf(strut.target));
+					n.AddValue(
+						"targetOffset",
+						strut.targetOffset.x + "," + strut.targetOffset.y + "," + strut.targetOffset.z
+					);
+				}
+			}
+
+			base.OnSave(node);
+		}
+
+		public override void OnLoad(ConfigNode node)
+		{
+			if (nodeToLoad == null)
+				nodeToLoad = node;
+
+			base.OnLoad(node);
+		}
+
+		void printObj(object obj)
+		{
+			using (KSP.IO.TextWriter writer = TextWriter.CreateForType<string>("obj.cs"))
+			{
+				string str = printProperties(obj, TypeDescriptor.GetProperties(obj), 0);
+				writer.Write(str);
+				print(str);
+			}
+		}
+
+		string printProperties(object obj, PropertyDescriptorCollection collection, int I)
+		{
+			if (I > 2)
+				return "";
+
+			string prefix = "";
+			string str = "";
+			for (int T = 0; T < I; T++)
+			{
+				prefix += "    ";
+			}
+
+			str += "\n" + prefix + "#region";
+			foreach (PropertyDescriptor d in collection)
+			{
+				str += "\n" + prefix + d.Name + " = " + d.GetValue(obj);
+				str += printProperties(obj, d.GetChildProperties(obj), I + 1);
+			}
+			str += "\n" + prefix + "#endregion";
+			return str;
+		}
+
+		public override void OnUpdate()
+		{
+			bool eva = isValid(Util.Kerbal);
+			Events["ActivateCore"].active = !IsEnabled;
+			Events["DeactivateCore"].active = IsEnabled;
+			Events["BeginPlace"].active = !Placing && !Deleting && struts.Count < MaxStruts && eva;
+			Events["BeginDelete"].active = !Deleting && !Placing && struts.Count > 0 && eva;
+
+			if (nodeToLoad != null)
+			{
+				foreach (ConfigNode strut in nodeToLoad.GetNodes("QuantumStrut"))
+				{
+					Part parent = part.vessel.parts[Convert.ToInt32(strut.GetValue("parent"))];
+					Vector3 parentOffset = StringToVector3(strut.GetValue("parentOffset"));
+					Part target = part.vessel.parts[Convert.ToInt32(strut.GetValue("target"))];
+					Vector3 targetOffset = StringToVector3(strut.GetValue("targetOffset"));
+
+					if (isValid(parent) && isValid(target))
+						AddStrut(parent, parentOffset, target, targetOffset);
+				}
+				nodeToLoad = null;
+			}
+
+			if (eva)
+			{
+				InitLaser();
+				if (Placing)
+				{
+					RaycastHit info = new RaycastHit();
+					Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
+					bool hit = Physics.Raycast(ray, out info, Mathf.Infinity);
+					if (isValid(startPart))
+					{
+						Vector3 pos = startPart.transform.TransformPoint(startOffset);
+						ray = new Ray(pos, (info.point - pos).normalized);
+						hit = Physics.Raycast(ray, out info, 10);
+					}
+
+					if (Input.GetMouseButtonUp(0))
+					{
+						if (hit)
+						{
+							if (!isValid(startPart))
+							{
+								startPart = partFromRaycast(info);
+								if (isValid(startPart))
+									startOffset = startPart.transform.InverseTransformPoint(info.point);
+							}
+							else if (!isValid(endPart))
+							{
+								Part p = partFromRaycast(info);
+								if (isValid(p))
+								{
+									if (p != startPart && startPart.vessel.parts.Contains(p))
+									{
+										endPart = p;
+										endOffset = endPart.transform.InverseTransformPoint(info.point);
+
+										AddStrut(startPart, startOffset, endPart, endOffset);
+									}
+									Placing = false;
+								}
+							}
+						}
+					}
+
+					if (isValid(startPart))
+					{
+						if (hit)
+						{
+							Part p = partFromRaycast(info);
+							Color c = Color.red;
+
+							if (isValid(p))
+							{
+								if (startPart.vessel.parts.Contains(p) && p != startPart)
+									c = Color.green;
+							}
+
+							lr.SetColors(c, c);
+							lr.SetPosition(0, startPart.transform.TransformPoint(startOffset));
+							lr.SetPosition(1, info.point);
+						}
+						else
+						{
+							lr.SetColors(Color.red, Color.red);
+							lr.SetPosition(0, startPart.transform.TransformPoint(startOffset));
+							lr.SetPosition(1, ray.GetPoint(10));
+						}
+					}
+				}
+				else
+				{
+					lr.SetPosition(0, Vector3.zero);
+					lr.SetPosition(1, Vector3.zero);
+				}
+
+				if (Deleting)
+				{
+					RaycastHit info = new RaycastHit();
+					Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
+					bool hit = Physics.Raycast(ray, out info, Mathf.Infinity);
+
+					CoreStrut closest = null;
+					float closestDist = Mathf.Infinity;
+					foreach (CoreStrut strut in struts)
+					{
+						strut.Selected = false;
+						if (hit)
+						{
+							Vector3 start = strut.parent.transform.TransformPoint(strut.parentOffset);
+							float d = Vector3.Distance(start, info.point);
+
+							if (d < 0.05 && d < closestDist)
+							{
+								closest = strut;
+								closestDist = d;
+							}
+						}
+					}
+
+					if (closest != null)
+						closest.Selected = true;
+
+					if (Input.GetMouseButtonUp(0))
+					{
+						if (closest != null)
+						{
+							closest.Destroy();
+							struts.Remove(closest);
+						}
+						Deleting = false;
+					}
+				}
+			}
+			else
+			{
+				DestroyLaser();
+			}
+
+			foreach (CoreStrut s in struts.ToArray())
+			{
+				if (IsEnabled)
+				{
+					if (s.Active)
+					{
+						if (PowerConsumption == 0 || (GetEnergy() > PowerConsumption * TimeWarp.fixedDeltaTime && part.RequestResource(
+							                      "ElectricCharge",
+							                      PowerConsumption * TimeWarp.fixedDeltaTime
+						                      ) > 0))
+						{
+							s.Active = true;
+						}
+						else
+						{
+							s.Active = false;
+						}
+					}
+					else
+					{
+						if (GetEnergy() > 5 * TimeWarp.fixedDeltaTime && part.RequestResource(
+							                      "ElectricCharge",
+							                      5 * TimeWarp.fixedDeltaTime
+						                      ) > 0)
+						{
+							s.Active = true;
+						}
+					}
+				}
+				else
+				{
+					s.Active = false;
+				}
+
+				s.Update();
+				if (s.isDestroyed)
+					struts.Remove(s);
+			}
+			base.OnUpdate();
+		}
+	}
 }
 

file:a/Strut.cs -> file:b/Strut.cs
--- a/Strut.cs
+++ b/Strut.cs
@@ -9,8 +9,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-
-//using System.Threading.Tasks;
 using UnityEngine;
 
 namespace QuantumStrut

file:a/Util.cs -> file:b/Util.cs
--- a/Util.cs
+++ b/Util.cs
@@ -10,130 +10,130 @@
 using System.ComponentModel;
 using System.Linq;
 using System.Text;
-//using System.Threading.Tasks;
 using KSP.IO;
 using UnityEngine;
 
 namespace QuantumStrut
 {
-    public static class Util
-    {
-        static System.Random r = new System.Random();
+	public static class Util
+	{
+		static System.Random r = new System.Random();
 
-        public static float Random(float min, float max)
-        {
-            return (float)((r.NextDouble() * (max - min)) + min);
-        }
+		public static float Random(float min, float max)
+		{
+			return (float)((r.NextDouble() * (max - min)) + min);
+		}
 
-        public static float Random()
-        {
-            return (float)r.NextDouble();
-        }
+		public static float Random()
+		{
+			return (float)r.NextDouble();
+		}
 
-        public static Part getTank(Part parent)
-        {
-            if (parent.Resources.Count != 0)
-                return parent;
+		public static Part getTank(Part parent)
+		{
+			if (parent.Resources.Count != 0)
+				return parent;
 
-            if (isValid(parent.parent) && parent.fuelCrossFeed)
-                return getTank(parent.parent);
+			if (isValid(parent.parent) && parent.fuelCrossFeed)
+				return getTank(parent.parent);
 
-            return null;
-        }
+			return null;
+		}
 
-        public static Vessel Kerbal
-        {
-            get
-            {
-                if (isValid(FlightGlobals.fetch.activeVessel) && FlightGlobals.fetch.activeVessel.isEVA)
-                    return FlightGlobals.fetch.activeVessel;
-                return null;
-            }
-        }
+		public static Vessel Kerbal
+		{
+			get
+			{
+				if (isValid(FlightGlobals.fetch.activeVessel) && FlightGlobals.fetch.activeVessel.isEVA)
+					return FlightGlobals.fetch.activeVessel;
+				return null;
+			}
+		}
 
-        public static bool isValid(UnityEngine.Object obj)
-        {
-            return (obj && obj != null);
-        }
+		public static bool isValid(UnityEngine.Object obj)
+		{
+			return (obj && obj != null);
+		}
 
-        public static void printObj(object obj)
-        {
-            using (KSP.IO.TextWriter writer = TextWriter.CreateForType<string>("obj.cs"))
-            {
-                string str = printProperties(obj, TypeDescriptor.GetProperties(obj), 0);
-                writer.Write(str);
-                MonoBehaviour.print(str);
-            }
-        }
+		public static void printObj(object obj)
+		{
+			using (KSP.IO.TextWriter writer = TextWriter.CreateForType<string>("obj.cs"))
+			{
+				string str = printProperties(obj, TypeDescriptor.GetProperties(obj), 0);
+				writer.Write(str);
+				MonoBehaviour.print(str);
+			}
+		}
 
-        static string printProperties(object obj, PropertyDescriptorCollection collection, int I)
-        {
-            if (I > 2) return "";
+		static string printProperties(object obj, PropertyDescriptorCollection collection, int I)
+		{
+			if (I > 2)
+				return "";
 
-            string prefix = "";
-            string str = "";
-            for (int T = 0; T < I; T++)
-            {
-                prefix += "    ";
-            }
+			string prefix = "";
+			string str = "";
+			for (int T = 0; T < I; T++)
+			{
+				prefix += "    ";
+			}
 
-            foreach (PropertyDescriptor d in collection)
-            {
-                str += "\n" + prefix + d.Name + " = " + d.GetValue(obj);
-            }
-            return str;
-        }
+			foreach (PropertyDescriptor d in collection)
+			{
+				str += "\n" + prefix + d.Name + " = " + d.GetValue(obj);
+			}
+			return str;
+		}
 
-        public static Part partFromGameObject(GameObject ob)
-        {
-            GameObject o = ob;
+		public static Part partFromGameObject(GameObject ob)
+		{
+			GameObject o = ob;
 
-            while (o)
-            {
-                Part p = Part.FromGO(o);
-                if (p && p != null)
-                {
-                    return p;
-                }
+			while (o)
+			{
+				Part p = Part.FromGO(o);
+				if (p && p != null)
+				{
+					return p;
+				}
 
-                if (o.transform.parent)
-                    o = o.transform.parent.gameObject;
-                else
-                    return null;
-            }
-            return null;
-        }
+				if (o.transform.parent)
+					o = o.transform.parent.gameObject;
+				else
+					return null;
+			}
+			return null;
+		}
 
-        public static Part partFromRaycast(RaycastHit hit)
-        {
-            return partFromGameObject(hit.collider.gameObject);
-        }
+		public static Part partFromRaycast(RaycastHit hit)
+		{
+			return partFromGameObject(hit.collider.gameObject);
+		}
 
-        public static Part partFromId(Vessel vessel, long id)
-        {
-            Console.WriteLine("Vessel Parts: " + vessel.Parts.Count);
-            foreach (Part p in vessel.Parts)
-            {
-                MonoBehaviour.print(p.uid + " ?= " + id + ": " + (p.uid == id));
-                if (p.uid == id)
-                    return p;
-            }
-            return null;
-        }
+		public static Part partFromId(Vessel vessel, long id)
+		{
+			Console.WriteLine("Vessel Parts: " + vessel.Parts.Count);
+			foreach (Part p in vessel.Parts)
+			{
+				MonoBehaviour.print(p.uid + " ?= " + id + ": " + (p.uid == id));
+				if (p.uid == id)
+					return p;
+			}
+			return null;
+		}
 
-        public static float GetEnergy(Vessel vessel)
-        {
-            double energy = 0;
-            foreach (Part p in vessel.parts)
-            {
-                foreach (PartResource r in p.Resources)
-                {
-                    if (r.resourceName == "ElectricCharge")
-                        energy += r.amount;
-                }
-            }
-            return (float)energy;
-        }
-    }
+		public static float GetEnergy(Vessel vessel)
+		{
+			double energy = 0;
+			foreach (Part p in vessel.parts)
+			{
+				foreach (PartResource r in p.Resources)
+				{
+					if (r.resourceName == "ElectricCharge")
+						energy += r.amount;
+				}
+			}
+			return (float)energy;
+		}
+	}
 }