diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6d2ca43
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/Plugin/Chiller/*.suo
+/Plugin/Chiller/bin
+/Plugin/Chiller/obj
diff --git a/Parts/chillerRadPanelLg.cfg b/Parts/chillerRadPanelLg.cfg
new file mode 100644
index 0000000..850b9ac
--- /dev/null
+++ b/Parts/chillerRadPanelLg.cfg
@@ -0,0 +1,47 @@
+PART
+{
+ name = chillerRadPanelLg
+ module = Part
+ author = Youen
+ MODEL
+ {
+ model = Squad/Parts/Thermal/RadiatorPanels/radPanelLg
+ }
+ rescaleFactor = 1.0
+ node_attach = 0.0, 0.0, -0.0, 0.0, 0.0, -1.0
+ TechRequired = basicScience
+ entryCost = 2200
+ cost = 450
+ category = Utility
+ manufacturer = Probodobodyne Inc
+ subcategory = 0
+ title = Chiller (large)
+ description = A radially attachable radiator panel to help dissipate heat into space. This system uses a closed refrigerant circuit and a compressor to move heat from the attached part to itself, allowing very low target temperatures. The chiller panel can accordingly become very hot.
+ attachRules = 0,1,0,1,1
+ mass = 0.05
+ dragModelType = default
+ maximum_drag = 0.2
+ minimum_drag = 0.2
+ angularDrag = 2
+ crashTolerance = 12
+ maxTemp = 2500 // = 2900
+ bulkheadProfiles = srf
+ tags = cool fixed heat moderat radiat static temperat therm
+ emissiveConstant = 0.90
+ heatConductivity = 0.001 //They have built in insulators
+ thermalMassModifier = 5
+ radiatorHeadroom = 0.75
+ skinInternalConductionMult = 2000
+
+ MODULE
+ {
+ name = ModuleActiveRadiator
+ maxEnergyTransfer = 0 // This is just to appear as a radiator to other radiators, but the actual energy transfer happens in ModuleChiller
+ }
+
+ MODULE
+ {
+ name = ModuleChiller
+ MaxPower = 50
+ }
+}
diff --git a/Plugin/Chiller/Chiller.csproj b/Plugin/Chiller/Chiller.csproj
new file mode 100644
index 0000000..001e8f9
--- /dev/null
+++ b/Plugin/Chiller/Chiller.csproj
@@ -0,0 +1,59 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {D05D19C4-C5DA-4F8F-A2A8-B0FA54F2BAE4}
+ Library
+ Properties
+ Chiller
+ Chiller
+ v3.5
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\..\Jeux\KSP_1_1_3\KSP_Data\Managed\Assembly-CSharp.dll
+ False
+
+
+ ..\..\..\..\..\Jeux\KSP_1_1_3\KSP_Data\Managed\UnityEngine.dll
+ False
+
+
+ ..\..\..\..\..\Jeux\KSP_1_1_3\KSP_Data\Managed\UnityEngine.UI.dll
+ False
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Plugin/Chiller/Chiller.sln b/Plugin/Chiller/Chiller.sln
new file mode 100644
index 0000000..0ae6c91
--- /dev/null
+++ b/Plugin/Chiller/Chiller.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chiller", "Chiller.csproj", "{D05D19C4-C5DA-4F8F-A2A8-B0FA54F2BAE4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D05D19C4-C5DA-4F8F-A2A8-B0FA54F2BAE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D05D19C4-C5DA-4F8F-A2A8-B0FA54F2BAE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D05D19C4-C5DA-4F8F-A2A8-B0FA54F2BAE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D05D19C4-C5DA-4F8F-A2A8-B0FA54F2BAE4}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Plugin/Chiller/ModuleChiller.cs b/Plugin/Chiller/ModuleChiller.cs
new file mode 100644
index 0000000..ee36210
--- /dev/null
+++ b/Plugin/Chiller/ModuleChiller.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+namespace Chiller
+{
+ public class ModuleChiller : PartModule
+ {
+ ///
+ /// Maximum electric power this Chiller unit can draw, in KSP Electric Charge per second. Since this mod assumes 1 EC = 1 kW.s, the value indicated here can be considered to be in kilowatts.
+ ///
+ [KSPField(isPersistant = false, guiActive = false)]
+ public float MaxPower = 10;
+
+ ///
+ /// Coefficient Of Performance (heat removed from the chilled part, divided by the electric power consumed)
+ /// Note that the electric power also ends up heating the radiator panel (in addition to the heat taken from the cooled part)
+ ///
+ [KSPField(isPersistant = false, guiActive = false)]
+ public float COP = 4;
+
+ ///
+ /// Target temperature for the part on which the Chiller is attached, in Kelvins. If the temperature of that part is above the set-point, the Chiller turns on to cool it.
+ ///
+ [KSPField(isPersistant=true, guiActive=true, guiName="Set-point (K)")]
+ [UI_FloatRange(minValue = 10, maxValue = 400)]
+ public float SetPoint = 100;
+
+ [KSPField(isPersistant = false, guiActive = false)]
+ public float SetPointThreshold = 5;
+
+ [KSPField(isPersistant = false, guiActive = true)]
+ public string Status = "Offline";
+
+ [KSPField(isPersistant = false, guiActive = true, guiName="Heat transfer")]
+ public string HeatTransferStatus = "Offline";
+
+ [KSPField(isPersistant = false, guiActive = true, guiName = "Temperature")]
+ public string CurrentTemperature = "";
+
+ [KSPField(isPersistant = false, guiActive = true, guiName = "Electric consumption")]
+ public string ElectricStatus = "";
+
+ private bool WasCooling = false;
+ private float CurrentHeatTransfer = 0;
+
+ public void FixedUpdate()
+ {
+ var cooledPart = part.parent;
+ bool isActive = part.FindModuleImplementing().IsCooling;
+
+ Status = "Stand-by";
+ CurrentTemperature = cooledPart.temperature.ToString("0.00") + " K";
+ ElectricStatus = "";
+ bool cooling = false;
+
+ float energyToTransfer = 0;
+
+ if (isActive)
+ {
+ if (cooledPart.temperature > SetPoint + (WasCooling ? 0 : SetPointThreshold))
+ {
+ float maxRadiatorTemperature = (float)part.maxTemp * (float)part.radiatorHeadroom;
+ if ((float)part.temperature >= maxRadiatorTemperature - (WasCooling ? 0 : SetPointThreshold))
+ {
+ Status = "Radiator too hot";
+ }
+ else
+ {
+ float neededCoolingEnergy = ((float)cooledPart.temperature - SetPoint) * (float)cooledPart.thermalMass / TimeWarp.fixedDeltaTime;
+ float availableHeatEnergy = (maxRadiatorTemperature - (float)part.temperature) * (float)part.thermalMass * (COP / (COP + 1)) / TimeWarp.fixedDeltaTime;
+ energyToTransfer = Mathf.Min(neededCoolingEnergy, availableHeatEnergy, MaxPower * COP);
+ }
+ }
+ }
+ else
+ {
+ Status = "Off";
+ }
+
+ if (energyToTransfer > CurrentHeatTransfer)
+ {
+ // slow transfer startup, to simulate progressive refrigerant compression as the pump is started
+ float c = 1.0f / (1.0f + TimeWarp.fixedDeltaTime);
+ CurrentHeatTransfer = CurrentHeatTransfer * c + energyToTransfer * (1.0f - c);
+ }
+ else
+ {
+ // immediate reactivity when slowing down to avoid overshooting
+ CurrentHeatTransfer = energyToTransfer;
+ }
+
+ if(energyToTransfer > 0)
+ {
+ float requiredElectricCharge = CurrentHeatTransfer * TimeWarp.fixedDeltaTime / COP;
+ var electricCharge = vessel.GetActiveResources().SingleOrDefault(r => r.info.name == "ElectricCharge");
+ float totalAvailableElectricEnergy = electricCharge == null ? 0.0f : (float)electricCharge.amount;
+
+ // we don't use electric charge at all if battery is low, to avoid disabling more critical systems, such as command modules etc.
+ float electricChargeMargin = 10;
+ float availableElectricEnergy;
+ if (totalAvailableElectricEnergy > requiredElectricCharge + electricChargeMargin)
+ {
+ availableElectricEnergy = part.RequestResource(electricCharge.info.id, Math.Min(requiredElectricCharge, totalAvailableElectricEnergy - electricChargeMargin));
+ }
+ else
+ {
+ availableElectricEnergy = 0;
+ }
+
+ if (availableElectricEnergy < requiredElectricCharge * 0.9f)
+ {
+ Status = "Not enough power";
+ CurrentHeatTransfer = availableElectricEnergy * COP;
+ }
+ else
+ {
+ Status = "Cooling";
+ }
+
+ cooledPart.AddThermalFlux(-CurrentHeatTransfer * 2);
+ part.AddThermalFlux(CurrentHeatTransfer * 2 * (COP + 1) / COP);
+
+ ElectricStatus = availableElectricEnergy.ToString("0.00") + " kW";
+
+ cooling = true;
+ }
+
+ HeatTransferStatus = CurrentHeatTransfer.ToString("0.00") + " kW (" + (CurrentHeatTransfer / (float)cooledPart.thermalMass).ToString("0.00") + " K/s)";
+
+ WasCooling = cooling;
+ }
+ }
+}
diff --git a/Plugin/Chiller/Properties/AssemblyInfo.cs b/Plugin/Chiller/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1e491c6
--- /dev/null
+++ b/Plugin/Chiller/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+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("Chiller")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Chiller")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2016")]
+[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("d76b9050-9846-48fa-bc18-ab18f04d39ba")]
+
+// 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")]