diff --git a/DeepFreeze.zip b/DeepFreeze.zip index 3495a74..ae55a32 100644 Binary files a/DeepFreeze.zip and b/DeepFreeze.zip differ diff --git a/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version b/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version index 5cf1802..cf04e88 100644 --- a/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version +++ b/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version @@ -2,7 +2,7 @@ "NAME":"DeepFreeze Continued...", "URL":"http://ksp-avc.cybutek.net/version.php?id=183", "DOWNLOAD":"https://kerbalstuff.com/mod/895/DeepFreeze%20Continued...", -"VERSION":{"MAJOR":0,"MINOR":20,"PATCH":0,"BUILD":0}, +"VERSION":{"MAJOR":0,"MINOR":20,"PATCH":1,"BUILD":0}, "KSP_VERSION":{"MAJOR":1,"MINOR":0,"PATCH":5}, "KSP_VERSION_MIN":{"MAJOR":1,"MINOR":0,"PATCH":3}, "KSP_VERSION_MAX":{"MAJOR":1,"MINOR":0,"PATCH":5} diff --git a/GameData/REPOSoftTech/DeepFreeze/Plugins/DeepFreeze.dll b/GameData/REPOSoftTech/DeepFreeze/Plugins/DeepFreeze.dll index df1fa5e..a46c2d5 100644 Binary files a/GameData/REPOSoftTech/DeepFreeze/Plugins/DeepFreeze.dll and b/GameData/REPOSoftTech/DeepFreeze/Plugins/DeepFreeze.dll differ diff --git a/GameData/REPOSoftTech/DeepFreeze/Plugins/DeepFreeze.dll.mdb b/GameData/REPOSoftTech/DeepFreeze/Plugins/DeepFreeze.dll.mdb deleted file mode 100644 index 9c9bf87..0000000 Binary files a/GameData/REPOSoftTech/DeepFreeze/Plugins/DeepFreeze.dll.mdb and /dev/null differ diff --git a/Source/Changelog.txt b/Source/Changelog.txt index 1a865e9..d4645a3 100644 --- a/Source/Changelog.txt +++ b/Source/Changelog.txt @@ -1,4 +1,7 @@ -[B]V0.20.0.0 "External Radial Pods"[/B] +V0.20.1.0 "Bug fixes & Enhancements" +Fixed sound glitch/issue with CRY-0300R when attaching more than one in symmetry mode in the editor. +For Other Modder/Mods API interface re-written providing API via reflection class (no hard dependancy) - of no relevance to users. +[B]V0.20.0.0 "External Radial Pods"[/B] Added new Radial External Cryopod - The CRY-0300R. A single kerbal Cryopod part that can be radially attached. The CRY-0300R also has an attach point at the top of the pod. Great for adding radial pods to your vessel or inside a SpacePlane CargoBay! Fits inside the Mk-2 & Mk-3 Cargo bays, the part does clip through the base of cargo bays as it is primarily designed to attach to the outside of a curved part. However, if you get creative you can fit it into a Cargo bay using girders or octaganol struts. diff --git a/Source/DFGameSettings.cs b/Source/DFGameSettings.cs index aa1362c..cd0808e 100644 --- a/Source/DFGameSettings.cs +++ b/Source/DFGameSettings.cs @@ -31,11 +31,11 @@ internal class DFGameSettings // knownKACAlarms = all Kerbal Alarm Clock alarms that are associated with a DeppFreezer knownVessels entry public const string configNodeName = "DFGameSettings"; - public bool Enabled { get; set; } - internal Dictionary KnownFrozenKerbals { get; private set; } - internal Dictionary knownVessels { get; private set; } - internal Dictionary knownFreezerParts { get; private set; } - internal Dictionary knownKACAlarms { get; private set; } + public bool Enabled; + internal Dictionary KnownFrozenKerbals; + internal Dictionary knownVessels; + internal Dictionary knownFreezerParts; + internal Dictionary knownKACAlarms; internal DFGameSettings() { diff --git a/Source/DFIntMemory.cs b/Source/DFIntMemory.cs index 740cb5c..ea17152 100644 --- a/Source/DFIntMemory.cs +++ b/Source/DFIntMemory.cs @@ -121,7 +121,7 @@ private void Start() private void OnDestroy() { - this.Log_Debug("DFIntMemory OnDestroy"); + Utilities.Log("DFIntMemory", "OnDestroy"); //destroy the event hook for KAC if (KACWrapper.APIReady) KACWrapper.KAC.onAlarmStateChanged -= KAC_onAlarmStateChanged; @@ -130,8 +130,7 @@ private void OnDestroy() GameEvents.onVesselLoaded.Remove(onVesselLoad); GameEvents.onVesselCreate.Remove(onVesselCreate); GameEvents.onPartCouple.Remove(onPartCouple); - GameEvents.onGUIEngineersReportReady.Remove(AddTests); - this.Log_Debug("DFIntMemory end OnDestroy"); + GameEvents.onGUIEngineersReportReady.Remove(AddTests); } private void Update() diff --git a/Source/DFWrapper.cs b/Source/DFWrapper.cs new file mode 100644 index 0000000..2360556 --- /dev/null +++ b/Source/DFWrapper.cs @@ -0,0 +1,742 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +// TODO: Change this namespace to something specific to your plugin here. +//EG: +// namespace MyPlugin_KACWrapper +namespace DeepFreezeWrapper +{ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BELOW HERE SHOULD NOT BE EDITED - this links to the loaded DeepFreeze module without requiring a Hard Dependancy + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// The Wrapper class to access DeepFreeze from another plugin + /// + public class DFWrapper + { + protected static System.Type DFType; + protected static System.Type KerbalInfoType; + protected static System.Type DeepFreezerType; + protected static System.Type FrznCrewMbrType; + protected static Object actualDF = null; + + /// + /// This is the DeepFreeze object + /// + /// SET AFTER INIT + /// + public static DFAPI DeepFreezeAPI; + + /// + /// Whether we found the DeepFreeze assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return (DFType != null); } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return (DeepFreezeAPI != null); } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _DFWrapped; + + /// + /// Whether the object has been wrapped and the APIReady flag is set in the real DeepFreeze + /// + public static Boolean APIReady { get { return _DFWrapped && DeepFreezeAPI.APIReady; } } + + /// + /// This method will set up the DeepFreeze object and wrap all the methods/functions + /// + /// + /// Bool indicating success of call + /// + public static Boolean InitDFWrapper() + { + try + { + //reset the internal objects + _DFWrapped = false; + actualDF = null; + DeepFreezeAPI = null; + LogFormatted("Attempting to Grab DeepFreeze Types..."); + + //find the base type + DFType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.DeepFreeze"); + + if (DFType == null) + { + return false; + } + + LogFormatted("DeepFreeze Version:{0}", DFType.Assembly.GetName().Version.ToString()); + + //now the KerbalInfo Type + KerbalInfoType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.KerbalInfo"); + + if (KerbalInfoType == null) + { + return false; + } + + //now the DeepFreezer (partmodule) Type + DeepFreezerType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.DeepFreezer"); + + if (DeepFreezerType == null) + { + return false; + } + + //now the FrznCrewMbr Type + FrznCrewMbrType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.FrznCrewMbr"); + + if (FrznCrewMbrType == null) + { + return false; + } + + //now grab the running instance + LogFormatted("Got Assembly Types, grabbing Instance"); + try + { + actualDF = DFType.GetField("Instance", BindingFlags.Public | BindingFlags.Static).GetValue(null); + } + catch (Exception) + { + LogFormatted("No Instance found - most likely you have an old DeepFreeze installed"); + return false; + } + if (actualDF == null) + { + LogFormatted("Failed grabbing Instance"); + return false; + } + + //If we get this far we can set up the local object and its methods/functions + LogFormatted("Got Instance, Creating Wrapper Objects"); + DeepFreezeAPI = new DFAPI(actualDF); + _DFWrapped = true; + return true; + } + catch (Exception ex) + { + LogFormatted("Unable to setup InitDFWrapper Reflection"); + LogFormatted("Exception: {0}", ex); + _DFWrapped = false; + return false; + } + } + + /// + /// The API Class that is an analogue of the real DeepFreeze. This lets you access all the API-able properties and Methods of the DeepFreeze + /// + public class DFAPI + { + internal DFAPI(Object a) + { + try + { + //store the actual object + actualDFAPI = a; + + //these sections get and store the reflection info and actual objects where required. Later in the properties we then read the values from the actual objects + //for events we also add a handler + //Object tstfrozenkerbals = DFType.GetField("FrozenKerbals", BindingFlags.Public | BindingFlags.Static).GetValue(null); + + LogFormatted("Getting APIReady Object"); + APIReadyField = DFType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); + LogFormatted("Success: " + (APIReadyField != null).ToString()); + + LogFormatted("Getting FrozenKerbals Object"); + FrozenKerbalsMethod = DFType.GetMethod("get_FrozenKerbals", BindingFlags.Public | BindingFlags.Instance); + actualFrozenKerbals = FrozenKerbalsMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualFrozenKerbals != null).ToString()); + } + catch (Exception ex) + { + LogFormatted("Unable to Instantiate DFAPI object using Reflection"); + LogFormatted("Exception: {0}", ex); + } + } + + private Object actualDFAPI; + + private FieldInfo APIReadyField; + /// + /// Whether the APIReady flag is set in the real KAC + /// + /// + /// Bool Indicating if DeepFreeze is ready for API calls + /// + public bool APIReady + { + get + { + if (APIReadyField == null) + return false; + + return (Boolean)APIReadyField.GetValue(null); + } + } + + #region Frozenkerbals + + private Object actualFrozenKerbals; + private MethodInfo FrozenKerbalsMethod; + + /// + /// The dictionary of Frozen Kerbals that are currently active in game + /// + /// + /// Dictionary of Frozen Kerbals + /// + internal Dictionary FrozenKerbals + { + get + { + if (FrozenKerbalsMethod == null) + return null; + //Object tstfrozenkerbals = DFType.GetField("FrozenKerbals", BindingFlags.Public | BindingFlags.Static).GetValue(null); + FieldInfo gamesettingsfield = DFType.GetField("DFgameSettings", BindingFlags.Instance | BindingFlags.NonPublic); + Object gamesettings = gamesettingsfield.GetValue(actualDFAPI); + actualFrozenKerbals = FrozenKerbalsMethod.Invoke(actualDFAPI, null); + Dictionary returnvalue = new Dictionary(); + returnvalue = ExtractFrozenKerbalDict(actualFrozenKerbals); + return returnvalue; + } + } + + /// + /// This converts the actualFrozenKerbals actual object to a new dictionary for consumption + /// + /// + /// Dictionary of Frozen Kerbals + private Dictionary ExtractFrozenKerbalDict(Object actualFrozenKerbals) + { + Dictionary DictToReturn = new Dictionary(); + try + { + foreach (var item in (IDictionary)actualFrozenKerbals) + { + var typeitem = item.GetType(); + PropertyInfo[] itemprops = typeitem.GetProperties(BindingFlags.Instance | BindingFlags.Public); + string itemkey = (string)itemprops[0].GetValue(item, null); + object itemvalue = (object)itemprops[1].GetValue(item, null); + KerbalInfo itemkerbalinfo = new KerbalInfo(itemvalue); + DictToReturn[itemkey] = itemkerbalinfo; + } + } + catch (Exception ex) + { + LogFormatted("Unable to extract FrozenKerbals Dictionary: {0}", ex.Message); + } + return DictToReturn; + } + + #endregion Frozenkerbals + } + + #region DeepFreezerPart + + /// + /// The Class that is an analogue of the real DeepFreezer PartModule. This lets you access all the API-able properties and Methods of the DeepFreezer + /// + public class DeepFreezer + { + internal DeepFreezer(Object a) + { + actualDeepFreezer = a; + //Fields available from Freezer part + crewXferTOActiveMethod = DeepFreezerType.GetMethod("get_DFIcrewXferTOActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + crewXferTOActive = getcrewXferTOActive; + crewXferFROMActiveMethod = DeepFreezerType.GetMethod("get_DFIcrewXferFROMActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + crewXferFROMActive = getcrewXferFROMActive; + FreezerSizeMethod = DeepFreezerType.GetMethod("get_DFIFreezerSize", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FreezerSize = getFreezerSize; + TotalFrozenMethod = DeepFreezerType.GetMethod("get_DFITotalFrozen", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + TotalFrozen = getTotalFrozen; + FreezerSpaceMethod = DeepFreezerType.GetMethod("get_DFIFreezerSpace", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FreezerSpace = getFreezerSpace; + PartFullMethod = DeepFreezerType.GetMethod("get_DFIPartFull", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + PartFull = getPartFull; + IsFreezeActiveMethod = DeepFreezerType.GetMethod("get_DFIIsFreezeActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + IsFreezeActive = getIsFreezeActive; + IsThawActiveMethod = DeepFreezerType.GetMethod("get_DFIIsThawActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + IsThawActive = getIsThawActive; + FreezerOutofECMethod = DeepFreezerType.GetMethod("get_DFIFreezerOutofEC", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FreezerOutofEC = getFreezerOutofEC; + FrzrTmpMethod = DeepFreezerType.GetMethod("get_DFIFrzrTmp", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FrzrTmp = getFrzrTmp; + StoredCrewListMethod = DeepFreezerType.GetMethod("get_DFIStoredCrewList", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + actualStoredCrewList = StoredCrewListMethod.Invoke(actualDeepFreezer, null); + + //Methods + LogFormatted("Getting beginFreezeKerbalMethod Method"); + beginFreezeKerbalMethod = DeepFreezerType.GetMethod("beginFreezeKerbal", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (beginFreezeKerbalMethod != null).ToString()); + + LogFormatted("Getting beginThawKerbalMethod Method"); + beginThawKerbalMethod = DeepFreezerType.GetMethod("beginThawKerbal", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (beginThawKerbalMethod != null).ToString()); + } + + private Object actualDeepFreezer; + + #region DeepFreezerFieldMethods + + /// + /// True if a crewXfter TO this DeepFreezer part is currently active + /// + public bool crewXferTOActive; + + private MethodInfo crewXferTOActiveMethod; + + private bool getcrewXferTOActive + { + get { return (bool)crewXferTOActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if a crewXfter FROM this DeepFreezer part is currently active + /// + public bool crewXferFROMActive; + + private MethodInfo crewXferFROMActiveMethod; + + private bool getcrewXferFROMActive + { + get { return (bool)crewXferFROMActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The number of cryopods in this DeepFreezer + /// + public int FreezerSize; + + private MethodInfo FreezerSizeMethod; + + private int getFreezerSize + { + get { return (int)FreezerSizeMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The number of currently frozen Kerbals in this DeepFreezer + /// + public int TotalFrozen; + + private MethodInfo TotalFrozenMethod; + + private int getTotalFrozen + { + get { return (int)TotalFrozenMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The number of empty cryopods in this DeepFreezer + /// + public int FreezerSpace; + + private MethodInfo FreezerSpaceMethod; + + private int getFreezerSpace + { + get { return (int)FreezerSpaceMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if all the cryopods are taken in this DeepFreezer (includes, frozen and thawed kerbals). + /// + public bool PartFull; + + private MethodInfo PartFullMethod; + + private bool getPartFull + { + get { return (bool)PartFullMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if a Freeze kerbal event is currently active in this DeepFreezer + /// + public bool IsFreezeActive; + + private MethodInfo IsFreezeActiveMethod; + + private bool getIsFreezeActive + { + get { return (bool)IsFreezeActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if a Thaw kerbal event is currently active in this DeepFreezer + /// + public bool IsThawActive; + + private MethodInfo IsThawActiveMethod; + + private bool getIsThawActive + { + get { return (bool)IsThawActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if this DeepFreezer is currently out of Electric Charge + /// + public bool FreezerOutofEC; + + private MethodInfo FreezerOutofECMethod; + + private bool getFreezerOutofEC + { + get { return (bool)FreezerOutofECMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The current freezer temperature status of this DeepFreezer + /// + public FrzrTmpStatus FrzrTmp; + + private MethodInfo FrzrTmpMethod; + + private FrzrTmpStatus getFrzrTmp + { + get { return (FrzrTmpStatus)FrzrTmpMethod.Invoke(actualDeepFreezer, null); } + } + + private Object actualStoredCrewList; + private MethodInfo StoredCrewListMethod; + + /// + /// a List of all Frozen Crew in this DeepFreezer + /// + public FrznCrewList StoredCrewList + { + get { return ExtractStoredCrewList(actualStoredCrewList); } + } + + /// + /// This converts the StoredCrewList actual object to a new List for consumption + /// + /// + /// + private FrznCrewList ExtractStoredCrewList(Object actualStoredCrewList) + { + FrznCrewList ListToReturn = new FrznCrewList(); + try + { + //iterate each "value" in the dictionary + + foreach (var item in (IList)actualStoredCrewList) + { + FrznCrewMbr r1 = new FrznCrewMbr(item); + ListToReturn.Add(r1); + } + } + catch (Exception ex) + { + LogFormatted("Arrggg: {0}", ex.Message); + //throw ex; + // + } + return ListToReturn; + } + + #endregion DeepFreezerFieldMethods + + #region DeepFreezerMethods + + private MethodInfo beginFreezeKerbalMethod; + + /// + /// Begin the Freezing of a Kerbal + /// + /// ProtoCrewMember that you want frozen + /// Bool indicating success of call + public bool beginFreezeKerbal(ProtoCrewMember CrewMember) + { + try + { + beginFreezeKerbalMethod.Invoke(actualDeepFreezer, new System.Object[] { CrewMember }); + return true; + } + catch (Exception ex) + { + LogFormatted("Arrggg: {0}", ex.Message); + return false; + } + } + + private MethodInfo beginThawKerbalMethod; + + /// + /// Begin the Thawing of a Kerbal + /// + /// string containing the name of the kerbal you want thawed + /// Bool indicating success of call + public bool beginThawKerbal(string frozenkerbal) + { + try + { + beginThawKerbalMethod.Invoke(actualDeepFreezer, new System.Object[] { frozenkerbal }); + return true; + } + catch (Exception ex) + { + LogFormatted("Arrggg: {0}", ex.Message); + return false; + } + } + + #endregion DeepFreezerMethods + } + + public enum FrzrTmpStatus + { + OK = 0, + WARN = 1, + RED = 2, + } + + /// + /// The Class that is an analogue of the real FrznCrewMbr as part of the StoredCrewList field in the DeepFreezer PartModule. + /// + public class FrznCrewMbr + { + internal FrznCrewMbr(Object a) + { + actualFrznCrewMbr = a; + CrewNameMethod = FrznCrewMbrType.GetMethod("get_CrewName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + CrewName = getCrewName; + SeatIdxMethod = FrznCrewMbrType.GetMethod("get_SeatIdx", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + SeatIdx = getSeatIdx; + VesselIDMethod = FrznCrewMbrType.GetMethod("get_VesselID", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + VesselID = getVesselID; + VesselNameMethod = FrznCrewMbrType.GetMethod("get_VesselName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + VesselName = getVesselName; + } + + private Object actualFrznCrewMbr; + + + /// + /// Crew Members Name + /// + public string CrewName; + + private MethodInfo CrewNameMethod; + + private string getCrewName + { + get { return (string)CrewNameMethod.Invoke(actualFrznCrewMbr, null); } + } + + /// + /// Seat Index for Crew member + /// + public int SeatIdx; + + private MethodInfo SeatIdxMethod; + + private int getSeatIdx + { + get { return (int)SeatIdxMethod.Invoke(actualFrznCrewMbr, null); } + } + + /// + /// Vessel ID + /// + public Guid VesselID; + + private MethodInfo VesselIDMethod; + + private Guid getVesselID + { + get { return (Guid)VesselIDMethod.Invoke(actualFrznCrewMbr, null); } + } + + /// + /// Vessel Name + /// + public string VesselName; + + private MethodInfo VesselNameMethod; + + private string getVesselName + { + get { return (string)VesselNameMethod.Invoke(actualFrznCrewMbr, null); } + } + } + + public class FrznCrewList : List + { + } + + #endregion DeepFreezerPart + + /// + /// The Value Class of the FrozenCrewList Dictionary that is an analogue of the real FrozenKerbals Dictionary in the DeepFreezer Class. + /// + public class KerbalInfo + { + internal KerbalInfo(Object a) + { + actualFrozenKerbalInfo = a; + lastUpdateField = KerbalInfoType.GetField("lastUpdate"); + statusField = KerbalInfoType.GetField("status"); + typeField = KerbalInfoType.GetField("type"); + vesselIDField = KerbalInfoType.GetField("vesselID"); + vesselNameField = KerbalInfoType.GetField("vesselName"); + partIDField = KerbalInfoType.GetField("partID"); + seatIdxField = KerbalInfoType.GetField("seatIdx"); + seatNameField = KerbalInfoType.GetField("seatName"); + experienceTraitNameField = KerbalInfoType.GetField("experienceTraitName"); + } + + private Object actualFrozenKerbalInfo; + + private FieldInfo lastUpdateField; + + /// + /// last time the FrozenKerbalInfo was updated + /// + public double lastUpdate + { + get { return (double)lastUpdateField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo statusField; + + /// + /// RosterStatus of the frozen kerbal + /// + public ProtoCrewMember.RosterStatus status + { + get { return (ProtoCrewMember.RosterStatus)statusField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo typeField; + + /// + /// KerbalType of the frozen kerbal + /// + public ProtoCrewMember.KerbalType type + { + get { return (ProtoCrewMember.KerbalType)typeField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo vesselIDField; + + /// + /// Guid of the vessel the frozen kerbal is aboard + /// + public Guid vesselID + { + get { return (Guid)vesselIDField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo vesselNameField; + + /// + /// Name of the vessel the frozen kerbal is aboard + /// + public string vesselName + { + get { return (string)vesselNameField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo partIDField; + + /// + /// partID of the vessel part the frozen kerbal is aboard + /// + public uint partID + { + get { return (uint)partIDField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo seatIdxField; + + /// + /// seat index that the frozen kerbal is in + /// + public int seatIdx + { + get { return (int)seatIdxField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo seatNameField; + + /// + /// seat name that the frozen kerbal is in + /// + public string seatName + { + get { return (string)seatNameField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo experienceTraitNameField; + + /// + /// name of the experience trait for the frozen kerbal + /// + public string experienceTraitName + { + get { return (string)experienceTraitNameField.GetValue(actualFrozenKerbalInfo); } + } + } + + #region Logging Stuff + + /// + /// Some Structured logging to the debug file - ONLY RUNS WHEN DLL COMPILED IN DEBUG MODE + /// + /// Text to be printed - can be formatted as per String.format + /// Objects to feed into a String.format + [System.Diagnostics.Conditional("DEBUG")] + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + LogFormatted(Message, strParams); + } + + /// + /// Some Structured logging to the debug file + /// + /// Text to be printed - can be formatted as per String.format + /// Objects to feed into a String.format + internal static void LogFormatted(String Message, params Object[] strParams) + { + Message = String.Format(Message, strParams); + String strMessageLine = String.Format("{0},{2}-{3},{1}", + DateTime.Now, Message, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, + System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); + UnityEngine.Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/DeepFreeze.cs b/Source/DeepFreeze.cs index 099b247..b40d35a 100644 --- a/Source/DeepFreeze.cs +++ b/Source/DeepFreeze.cs @@ -25,9 +25,10 @@ namespace DF [KSPScenario(ScenarioCreationOptions.AddToAllGames, GameScenes.SPACECENTER, GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.TRACKSTATION)] public class DeepFreeze : ScenarioModule, IDFInterface { - public static DeepFreeze Instance { get; private set; } - internal DFSettings DFsettings { get; private set; } - internal DFGameSettings DFgameSettings { get; private set; } + public static DeepFreeze Instance; + public static bool APIReady; + internal DFSettings DFsettings; + internal DFGameSettings DFgameSettings; private readonly string globalConfigFilename; private ConfigNode globalNode = new ConfigNode(); private readonly List children = new List(); @@ -36,14 +37,15 @@ public Dictionary FrozenKerbals { get { - return this.DFgameSettings.KnownFrozenKerbals; + return DFgameSettings.KnownFrozenKerbals; } } - protected DeepFreeze() + public DeepFreeze() { Utilities.Log("DeepFreeze", "Constructor"); Instance = this; + APIReady = false; DFsettings = new DFSettings(); DFgameSettings = new DFGameSettings(); globalConfigFilename = System.IO.Path.Combine(_AssemblyFolder, "Config.cfg").Replace("\\", "/"); @@ -91,6 +93,8 @@ public override void OnAwake() var child = gameObject.AddComponent(); children.Add(child); } + + } public override void OnLoad(ConfigNode gameNode) @@ -108,11 +112,13 @@ public override void OnLoad(ConfigNode gameNode) s.Load(globalNode); } } + APIReady = true; this.Log("Scenario: " + HighLogic.LoadedScene.ToString() + " OnLoad: \n " + gameNode + "\n" + globalNode); } public override void OnSave(ConfigNode gameNode) { + //APIReady = false; base.OnSave(gameNode); DFgameSettings.Save(gameNode); foreach (Savable s in children.Where(c => c is Savable)) @@ -133,6 +139,8 @@ protected void OnGameSceneLoadRequested(GameScenes gameScene) protected void OnDestroy() { this.Log("OnDestroy"); + Instance = null; + APIReady = false; foreach (Component child in children) { this.Log("DeepFreeze Child Destroy for " + child.name); diff --git a/Source/DeepFreeze.csproj b/Source/DeepFreeze.csproj index 712d828..30c4e5a 100644 --- a/Source/DeepFreeze.csproj +++ b/Source/DeepFreeze.csproj @@ -64,6 +64,7 @@ + diff --git a/Source/DeepFreezeGUI.cs b/Source/DeepFreezeGUI.cs index 2dcc26e..8c4e7d2 100644 --- a/Source/DeepFreezeGUI.cs +++ b/Source/DeepFreezeGUI.cs @@ -198,7 +198,7 @@ internal void OnDestroy() else { // Set up the stock toolbar - this.Log_Debug("Removing onGUIAppLauncher callbacks"); + Utilities.Log("DeepFreezeGUI", "Removing onGUIAppLauncher callbacks"); GameEvents.onGUIApplicationLauncherReady.Remove(OnGUIAppLauncherReady); if (this.stockToolbarButton != null) { diff --git a/Source/DeepFreeze_APITester/DeepFreeze_APITester.sln b/Source/DeepFreeze_APITester/DeepFreeze_APITester.sln new file mode 100644 index 0000000..91e22ba --- /dev/null +++ b/Source/DeepFreeze_APITester/DeepFreeze_APITester.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DF_APITester", "DeepFreeze_APITester\DF_APITester.csproj", "{1E041E3F-A16F-4830-B9E2-B6C118298E75}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1E041E3F-A16F-4830-B9E2-B6C118298E75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E041E3F-A16F-4830-B9E2-B6C118298E75}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E041E3F-A16F-4830-B9E2-B6C118298E75}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E041E3F-A16F-4830-B9E2-B6C118298E75}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Source/DeepFreeze_APITester/DeepFreeze_APITester/DFWrapper.cs b/Source/DeepFreeze_APITester/DeepFreeze_APITester/DFWrapper.cs new file mode 100644 index 0000000..37265ff --- /dev/null +++ b/Source/DeepFreeze_APITester/DeepFreeze_APITester/DFWrapper.cs @@ -0,0 +1,742 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +// TODO: Change this namespace to something specific to your plugin here. +//EG: +// namespace MyPlugin_DFAPIWrapper +namespace DF_APITester +{ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BELOW HERE SHOULD NOT BE EDITED - this links to the loaded DeepFreeze module without requiring a Hard Dependancy + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// The Wrapper class to access DeepFreeze from another plugin + /// + public class DFWrapper + { + protected static System.Type DFType; + protected static System.Type KerbalInfoType; + protected static System.Type DeepFreezerType; + protected static System.Type FrznCrewMbrType; + protected static Object actualDF = null; + + /// + /// This is the DeepFreeze object + /// + /// SET AFTER INIT + /// + public static DFAPI DeepFreezeAPI; + + /// + /// Whether we found the DeepFreeze assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return (DFType != null); } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return (DeepFreezeAPI != null); } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _DFWrapped; + + /// + /// Whether the object has been wrapped and the APIReady flag is set in the real DeepFreeze + /// + public static Boolean APIReady { get { return _DFWrapped && DeepFreezeAPI.APIReady; } } + + /// + /// This method will set up the DeepFreeze object and wrap all the methods/functions + /// + /// + /// Bool indicating success of call + /// + public static Boolean InitDFWrapper() + { + try + { + //reset the internal objects + _DFWrapped = false; + actualDF = null; + DeepFreezeAPI = null; + LogFormatted("Attempting to Grab DeepFreeze Types..."); + + //find the base type + DFType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.DeepFreeze"); + + if (DFType == null) + { + return false; + } + + LogFormatted("DeepFreeze Version:{0}", DFType.Assembly.GetName().Version.ToString()); + + //now the KerbalInfo Type + KerbalInfoType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.KerbalInfo"); + + if (KerbalInfoType == null) + { + return false; + } + + //now the DeepFreezer (partmodule) Type + DeepFreezerType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.DeepFreezer"); + + if (DeepFreezerType == null) + { + return false; + } + + //now the FrznCrewMbr Type + FrznCrewMbrType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "DF.FrznCrewMbr"); + + if (FrznCrewMbrType == null) + { + return false; + } + + //now grab the running instance + LogFormatted("Got Assembly Types, grabbing Instance"); + try + { + actualDF = DFType.GetField("Instance", BindingFlags.Public | BindingFlags.Static).GetValue(null); + } + catch (Exception) + { + LogFormatted("No Instance found - most likely you have an old DeepFreeze installed"); + return false; + } + if (actualDF == null) + { + LogFormatted("Failed grabbing Instance"); + return false; + } + + //If we get this far we can set up the local object and its methods/functions + LogFormatted("Got Instance, Creating Wrapper Objects"); + DeepFreezeAPI = new DFAPI(actualDF); + _DFWrapped = true; + return true; + } + catch (Exception ex) + { + LogFormatted("Unable to setup InitDFWrapper Reflection"); + LogFormatted("Exception: {0}", ex); + _DFWrapped = false; + return false; + } + } + + /// + /// The API Class that is an analogue of the real DeepFreeze. This lets you access all the API-able properties and Methods of the DeepFreeze + /// + public class DFAPI + { + internal DFAPI(Object a) + { + try + { + //store the actual object + actualDFAPI = a; + + //these sections get and store the reflection info and actual objects where required. Later in the properties we then read the values from the actual objects + //for events we also add a handler + //Object tstfrozenkerbals = DFType.GetField("FrozenKerbals", BindingFlags.Public | BindingFlags.Static).GetValue(null); + + LogFormatted("Getting APIReady Object"); + APIReadyField = DFType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); + LogFormatted("Success: " + (APIReadyField != null).ToString()); + + LogFormatted("Getting FrozenKerbals Object"); + FrozenKerbalsMethod = DFType.GetMethod("get_FrozenKerbals", BindingFlags.Public | BindingFlags.Instance); + actualFrozenKerbals = FrozenKerbalsMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualFrozenKerbals != null).ToString()); + } + catch (Exception ex) + { + LogFormatted("Unable to Instantiate DFAPI object using Reflection"); + LogFormatted("Exception: {0}", ex); + } + } + + private Object actualDFAPI; + + private FieldInfo APIReadyField; + /// + /// Whether the APIReady flag is set in the real KAC + /// + /// + /// Bool Indicating if DeepFreeze is ready for API calls + /// + public bool APIReady + { + get + { + if (APIReadyField == null) + return false; + + return (Boolean)APIReadyField.GetValue(null); + } + } + + #region Frozenkerbals + + private Object actualFrozenKerbals; + private MethodInfo FrozenKerbalsMethod; + + /// + /// The dictionary of Frozen Kerbals that are currently active in game + /// + /// + /// Dictionary of Frozen Kerbals + /// + internal Dictionary FrozenKerbals + { + get + { + if (FrozenKerbalsMethod == null) + return null; + //Object tstfrozenkerbals = DFType.GetField("FrozenKerbals", BindingFlags.Public | BindingFlags.Static).GetValue(null); + FieldInfo gamesettingsfield = DFType.GetField("DFgameSettings", BindingFlags.Instance | BindingFlags.NonPublic); + Object gamesettings = gamesettingsfield.GetValue(actualDFAPI); + actualFrozenKerbals = FrozenKerbalsMethod.Invoke(actualDFAPI, null); + Dictionary returnvalue = new Dictionary(); + returnvalue = ExtractFrozenKerbalDict(actualFrozenKerbals); + return returnvalue; + } + } + + /// + /// This converts the actualFrozenKerbals actual object to a new dictionary for consumption + /// + /// + /// Dictionary of Frozen Kerbals + private Dictionary ExtractFrozenKerbalDict(Object actualFrozenKerbals) + { + Dictionary DictToReturn = new Dictionary(); + try + { + foreach (var item in (IDictionary)actualFrozenKerbals) + { + var typeitem = item.GetType(); + PropertyInfo[] itemprops = typeitem.GetProperties(BindingFlags.Instance | BindingFlags.Public); + string itemkey = (string)itemprops[0].GetValue(item, null); + object itemvalue = (object)itemprops[1].GetValue(item, null); + KerbalInfo itemkerbalinfo = new KerbalInfo(itemvalue); + DictToReturn[itemkey] = itemkerbalinfo; + } + } + catch (Exception ex) + { + LogFormatted("Unable to extract FrozenKerbals Dictionary: {0}", ex.Message); + } + return DictToReturn; + } + + #endregion Frozenkerbals + } + + #region DeepFreezerPart + + /// + /// The Class that is an analogue of the real DeepFreezer PartModule. This lets you access all the API-able properties and Methods of the DeepFreezer + /// + public class DeepFreezer + { + internal DeepFreezer(Object a) + { + actualDeepFreezer = a; + //Fields available from Freezer part + crewXferTOActiveMethod = DeepFreezerType.GetMethod("get_DFIcrewXferTOActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + crewXferTOActive = getcrewXferTOActive; + crewXferFROMActiveMethod = DeepFreezerType.GetMethod("get_DFIcrewXferFROMActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + crewXferFROMActive = getcrewXferFROMActive; + FreezerSizeMethod = DeepFreezerType.GetMethod("get_DFIFreezerSize", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FreezerSize = getFreezerSize; + TotalFrozenMethod = DeepFreezerType.GetMethod("get_DFITotalFrozen", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + TotalFrozen = getTotalFrozen; + FreezerSpaceMethod = DeepFreezerType.GetMethod("get_DFIFreezerSpace", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FreezerSpace = getFreezerSpace; + PartFullMethod = DeepFreezerType.GetMethod("get_DFIPartFull", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + PartFull = getPartFull; + IsFreezeActiveMethod = DeepFreezerType.GetMethod("get_DFIIsFreezeActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + IsFreezeActive = getIsFreezeActive; + IsThawActiveMethod = DeepFreezerType.GetMethod("get_DFIIsThawActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + IsThawActive = getIsThawActive; + FreezerOutofECMethod = DeepFreezerType.GetMethod("get_DFIFreezerOutofEC", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FreezerOutofEC = getFreezerOutofEC; + FrzrTmpMethod = DeepFreezerType.GetMethod("get_DFIFrzrTmp", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FrzrTmp = getFrzrTmp; + StoredCrewListMethod = DeepFreezerType.GetMethod("get_DFIStoredCrewList", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + actualStoredCrewList = StoredCrewListMethod.Invoke(actualDeepFreezer, null); + + //Methods + LogFormatted("Getting beginFreezeKerbalMethod Method"); + beginFreezeKerbalMethod = DeepFreezerType.GetMethod("beginFreezeKerbal", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (beginFreezeKerbalMethod != null).ToString()); + + LogFormatted("Getting beginThawKerbalMethod Method"); + beginThawKerbalMethod = DeepFreezerType.GetMethod("beginThawKerbal", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (beginThawKerbalMethod != null).ToString()); + } + + private Object actualDeepFreezer; + + #region DeepFreezerFieldMethods + + /// + /// True if a crewXfter TO this DeepFreezer part is currently active + /// + public bool crewXferTOActive; + + private MethodInfo crewXferTOActiveMethod; + + private bool getcrewXferTOActive + { + get { return (bool)crewXferTOActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if a crewXfter FROM this DeepFreezer part is currently active + /// + public bool crewXferFROMActive; + + private MethodInfo crewXferFROMActiveMethod; + + private bool getcrewXferFROMActive + { + get { return (bool)crewXferFROMActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The number of cryopods in this DeepFreezer + /// + public int FreezerSize; + + private MethodInfo FreezerSizeMethod; + + private int getFreezerSize + { + get { return (int)FreezerSizeMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The number of currently frozen Kerbals in this DeepFreezer + /// + public int TotalFrozen; + + private MethodInfo TotalFrozenMethod; + + private int getTotalFrozen + { + get { return (int)TotalFrozenMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The number of empty cryopods in this DeepFreezer + /// + public int FreezerSpace; + + private MethodInfo FreezerSpaceMethod; + + private int getFreezerSpace + { + get { return (int)FreezerSpaceMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if all the cryopods are taken in this DeepFreezer (includes, frozen and thawed kerbals). + /// + public bool PartFull; + + private MethodInfo PartFullMethod; + + private bool getPartFull + { + get { return (bool)PartFullMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if a Freeze kerbal event is currently active in this DeepFreezer + /// + public bool IsFreezeActive; + + private MethodInfo IsFreezeActiveMethod; + + private bool getIsFreezeActive + { + get { return (bool)IsFreezeActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if a Thaw kerbal event is currently active in this DeepFreezer + /// + public bool IsThawActive; + + private MethodInfo IsThawActiveMethod; + + private bool getIsThawActive + { + get { return (bool)IsThawActiveMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// True if this DeepFreezer is currently out of Electric Charge + /// + public bool FreezerOutofEC; + + private MethodInfo FreezerOutofECMethod; + + private bool getFreezerOutofEC + { + get { return (bool)FreezerOutofECMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The current freezer temperature status of this DeepFreezer + /// + public FrzrTmpStatus FrzrTmp; + + private MethodInfo FrzrTmpMethod; + + private FrzrTmpStatus getFrzrTmp + { + get { return (FrzrTmpStatus)FrzrTmpMethod.Invoke(actualDeepFreezer, null); } + } + + private Object actualStoredCrewList; + private MethodInfo StoredCrewListMethod; + + /// + /// a List of all Frozen Crew in this DeepFreezer + /// + public FrznCrewList StoredCrewList + { + get { return ExtractStoredCrewList(actualStoredCrewList); } + } + + /// + /// This converts the StoredCrewList actual object to a new List for consumption + /// + /// + /// + private FrznCrewList ExtractStoredCrewList(Object actualStoredCrewList) + { + FrznCrewList ListToReturn = new FrznCrewList(); + try + { + //iterate each "value" in the dictionary + + foreach (var item in (IList)actualStoredCrewList) + { + FrznCrewMbr r1 = new FrznCrewMbr(item); + ListToReturn.Add(r1); + } + } + catch (Exception ex) + { + LogFormatted("Arrggg: {0}", ex.Message); + //throw ex; + // + } + return ListToReturn; + } + + #endregion DeepFreezerFieldMethods + + #region DeepFreezerMethods + + private MethodInfo beginFreezeKerbalMethod; + + /// + /// Begin the Freezing of a Kerbal + /// + /// ProtoCrewMember that you want frozen + /// Bool indicating success of call + public bool beginFreezeKerbal(ProtoCrewMember CrewMember) + { + try + { + beginFreezeKerbalMethod.Invoke(actualDeepFreezer, new System.Object[] { CrewMember }); + return true; + } + catch (Exception ex) + { + LogFormatted("Arrggg: {0}", ex.Message); + return false; + } + } + + private MethodInfo beginThawKerbalMethod; + + /// + /// Begin the Thawing of a Kerbal + /// + /// string containing the name of the kerbal you want thawed + /// Bool indicating success of call + public bool beginThawKerbal(string frozenkerbal) + { + try + { + beginThawKerbalMethod.Invoke(actualDeepFreezer, new System.Object[] { frozenkerbal }); + return true; + } + catch (Exception ex) + { + LogFormatted("Arrggg: {0}", ex.Message); + return false; + } + } + + #endregion DeepFreezerMethods + } + + public enum FrzrTmpStatus + { + OK = 0, + WARN = 1, + RED = 2, + } + + /// + /// The Class that is an analogue of the real FrznCrewMbr as part of the StoredCrewList field in the DeepFreezer PartModule. + /// + public class FrznCrewMbr + { + internal FrznCrewMbr(Object a) + { + actualFrznCrewMbr = a; + CrewNameMethod = FrznCrewMbrType.GetMethod("get_CrewName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + CrewName = getCrewName; + SeatIdxMethod = FrznCrewMbrType.GetMethod("get_SeatIdx", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + SeatIdx = getSeatIdx; + VesselIDMethod = FrznCrewMbrType.GetMethod("get_VesselID", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + VesselID = getVesselID; + VesselNameMethod = FrznCrewMbrType.GetMethod("get_VesselName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + VesselName = getVesselName; + } + + private Object actualFrznCrewMbr; + + + /// + /// Crew Members Name + /// + public string CrewName; + + private MethodInfo CrewNameMethod; + + private string getCrewName + { + get { return (string)CrewNameMethod.Invoke(actualFrznCrewMbr, null); } + } + + /// + /// Seat Index for Crew member + /// + public int SeatIdx; + + private MethodInfo SeatIdxMethod; + + private int getSeatIdx + { + get { return (int)SeatIdxMethod.Invoke(actualFrznCrewMbr, null); } + } + + /// + /// Vessel ID + /// + public Guid VesselID; + + private MethodInfo VesselIDMethod; + + private Guid getVesselID + { + get { return (Guid)VesselIDMethod.Invoke(actualFrznCrewMbr, null); } + } + + /// + /// Vessel Name + /// + public string VesselName; + + private MethodInfo VesselNameMethod; + + private string getVesselName + { + get { return (string)VesselNameMethod.Invoke(actualFrznCrewMbr, null); } + } + } + + public class FrznCrewList : List + { + } + + #endregion DeepFreezerPart + + /// + /// The Value Class of the FrozenCrewList Dictionary that is an analogue of the real FrozenKerbals Dictionary in the DeepFreezer Class. + /// + public class KerbalInfo + { + internal KerbalInfo(Object a) + { + actualFrozenKerbalInfo = a; + lastUpdateField = KerbalInfoType.GetField("lastUpdate"); + statusField = KerbalInfoType.GetField("status"); + typeField = KerbalInfoType.GetField("type"); + vesselIDField = KerbalInfoType.GetField("vesselID"); + vesselNameField = KerbalInfoType.GetField("vesselName"); + partIDField = KerbalInfoType.GetField("partID"); + seatIdxField = KerbalInfoType.GetField("seatIdx"); + seatNameField = KerbalInfoType.GetField("seatName"); + experienceTraitNameField = KerbalInfoType.GetField("experienceTraitName"); + } + + private Object actualFrozenKerbalInfo; + + private FieldInfo lastUpdateField; + + /// + /// last time the FrozenKerbalInfo was updated + /// + public double lastUpdate + { + get { return (double)lastUpdateField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo statusField; + + /// + /// RosterStatus of the frozen kerbal + /// + public ProtoCrewMember.RosterStatus status + { + get { return (ProtoCrewMember.RosterStatus)statusField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo typeField; + + /// + /// KerbalType of the frozen kerbal + /// + public ProtoCrewMember.KerbalType type + { + get { return (ProtoCrewMember.KerbalType)typeField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo vesselIDField; + + /// + /// Guid of the vessel the frozen kerbal is aboard + /// + public Guid vesselID + { + get { return (Guid)vesselIDField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo vesselNameField; + + /// + /// Name of the vessel the frozen kerbal is aboard + /// + public string vesselName + { + get { return (string)vesselNameField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo partIDField; + + /// + /// partID of the vessel part the frozen kerbal is aboard + /// + public uint partID + { + get { return (uint)partIDField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo seatIdxField; + + /// + /// seat index that the frozen kerbal is in + /// + public int seatIdx + { + get { return (int)seatIdxField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo seatNameField; + + /// + /// seat name that the frozen kerbal is in + /// + public string seatName + { + get { return (string)seatNameField.GetValue(actualFrozenKerbalInfo); } + } + + private FieldInfo experienceTraitNameField; + + /// + /// name of the experience trait for the frozen kerbal + /// + public string experienceTraitName + { + get { return (string)experienceTraitNameField.GetValue(actualFrozenKerbalInfo); } + } + } + + #region Logging Stuff + + /// + /// Some Structured logging to the debug file - ONLY RUNS WHEN DLL COMPILED IN DEBUG MODE + /// + /// Text to be printed - can be formatted as per String.format + /// Objects to feed into a String.format + [System.Diagnostics.Conditional("DEBUG")] + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + LogFormatted(Message, strParams); + } + + /// + /// Some Structured logging to the debug file + /// + /// Text to be printed - can be formatted as per String.format + /// Objects to feed into a String.format + internal static void LogFormatted(String Message, params Object[] strParams) + { + Message = String.Format(Message, strParams); + String strMessageLine = String.Format("{0},{2}-{3},{1}", + DateTime.Now, Message, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, + System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); + UnityEngine.Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/DeepFreeze_APITester/DeepFreeze_APITester/DF_APITester.cs b/Source/DeepFreeze_APITester/DeepFreeze_APITester/DF_APITester.cs new file mode 100644 index 0000000..6dae13e --- /dev/null +++ b/Source/DeepFreeze_APITester/DeepFreeze_APITester/DF_APITester.cs @@ -0,0 +1,193 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace DF_APITester +{ + [KSPAddon(KSPAddon.Startup.Flight, false)] + public class APITester : MonoBehaviour + { + + private List deepfreezers = new List(); + + //Temporary GUI display fields + private Rect DFwindowPos; + private static int windowID = 199999; + private Vector2 GUIscrollViewVector = Vector2.zero; + private GUIStyle sectionTitleStyle, statusStyle; + private int seats; + private bool isxferto; + private bool isxferfrom; + private bool isfreezeact; + private bool isthawact; + private bool outofec; + private bool partfull; + private int freeseats; + private DFWrapper.FrzrTmpStatus tmpsts; + private int totfrozen; + private DFWrapper.FrznCrewList frzncrewlst = new DFWrapper.FrznCrewList(); + private Dictionary DFFrozenKerbals = new Dictionary(); + + internal void Start() + { + Debug.Log("DFAPITESTER Start"); + DFwindowPos = new Rect(40, 40, 250, 400); + RenderingManager.AddToPostDrawQueue(3, this.onDraw); + } + + internal void OnDestroy() + { + RenderingManager.RemoveFromPostDrawQueue(3, this.onDraw); + } + + internal void Update() + { + if (Time.timeSinceLevelLoad < 2.0f) // Check not loading level + return; + + if (!DFWrapper.InstanceExists) // Check if DFWrapper has been initialized or not. If not try to initialize. + { + DFWrapper.InitDFWrapper(); + } + + if (DFWrapper.APIReady) // If the DeepFreeze API is Ready we do stuff with it. + { + DFFrozenKerbals.Clear(); + //Get the DeepFreeze Dictionary of all Frozen Kerbals in the current Game. + DFFrozenKerbals = DFWrapper.DeepFreezeAPI.FrozenKerbals; + + //Go through the active vessel and get all the DeepFreezer partmodules. + deepfreezers.Clear(); + if (FlightGlobals.ActiveVessel != null) + { + //Get a List of all the PartModules that are DeepFreezer class and store in deepfreezers List. + List cryofreezers = (from p in FlightGlobals.ActiveVessel.parts where p.Modules.Contains("DeepFreezer") select p).ToList(); + foreach (Part part in cryofreezers) + { + PartModule deepFreezer = (from PartModule pm in part.Modules where pm.moduleName == "DeepFreezer" select pm).SingleOrDefault(); + if (deepFreezer != null) + { + deepfreezers.Add(deepFreezer); + } + } + + //If we found any DeepFreezer partmodules + if (deepfreezers.Count == 1) + { + foreach (PartModule module in deepfreezers) + { + + //The DFWrapper.DeepFreezer class is a reflection class of the real DeepFreezer PartModule + DFWrapper.DeepFreezer freezer = new DFWrapper.DeepFreezer(module); + + //Populate fields for GUI display - NB: This only works for ONE freezer module in active vessel + //But is only for example purposes. If you want to do this for multiple modules then + // you will have to create your own Lists, etc. + seats = freezer.FreezerSize; + isxferto = freezer.crewXferTOActive; + isxferfrom = freezer.crewXferFROMActive; + isfreezeact = freezer.IsFreezeActive; + isthawact = freezer.IsThawActive; + outofec = freezer.FreezerOutofEC; + partfull = freezer.PartFull; + freeseats = freezer.FreezerSpace; + tmpsts = freezer.FrzrTmp; + totfrozen = freezer.TotalFrozen; + frzncrewlst = freezer.StoredCrewList; + } + } + } + } + } + + private void onDraw() + { + if (HighLogic.LoadedScene == GameScenes.FLIGHT) + { + GUI.skin = HighLogic.Skin; + DFwindowPos = GUILayout.Window(windowID, DFwindowPos, windowDF, "DeepFreeze API Test", GUILayout.ExpandWidth(true), + GUILayout.ExpandHeight(true), GUILayout.MinWidth(200), GUILayout.MinHeight(400)); + } + } + + private void windowDF(int id) + { + //Init styles + sectionTitleStyle = new GUIStyle(GUI.skin.label); + sectionTitleStyle.alignment = TextAnchor.MiddleLeft; + sectionTitleStyle.stretchWidth = true; + sectionTitleStyle.normal.textColor = Color.blue; + sectionTitleStyle.fontStyle = FontStyle.Bold; + + statusStyle = new GUIStyle(GUI.skin.label); + statusStyle.alignment = TextAnchor.MiddleLeft; + statusStyle.stretchWidth = true; + statusStyle.normal.textColor = Color.white; + + GUILayout.BeginVertical(); + GUIscrollViewVector = GUILayout.BeginScrollView(GUIscrollViewVector, false, false); + GUILayout.BeginVertical(); + + GUILayout.Label("# of FrozenKerbals " + DFFrozenKerbals.Count.ToString(), statusStyle); + GUILayout.Label("FreezerSize " + seats, statusStyle); + GUILayout.Label("FreezerSpace " + freeseats, statusStyle); + GUILayout.Label("TotalFrozen " + totfrozen, statusStyle); + GUILayout.Label("PartFull " + partfull, statusStyle); + GUILayout.Label("IsFreezeActive " + isfreezeact, statusStyle); + GUILayout.Label("IsThawActive " + isthawact, statusStyle); + GUILayout.Label("FreezerOutofEC " + outofec, statusStyle); + GUILayout.Label("crewXferTOActive " + isxferto, statusStyle); + GUILayout.Label("crewXferFROMActive " + isxferfrom, statusStyle); + GUILayout.Label("FrzrTmp " + tmpsts.ToString(), statusStyle); + GUILayout.Label("FrozenCrew:"); + if (frzncrewlst.Count == 0) + { + GUILayout.Label("NONE"); + } + else + { + foreach (DFWrapper.FrznCrewMbr frzncrewmbr in frzncrewlst) + { + GUILayout.BeginHorizontal(); + GUILayout.Label(frzncrewmbr.CrewName + " " + frzncrewmbr.SeatIdx + frzncrewmbr.VesselName); + if (GUILayout.Button("Thaw")) + { + //this is a nasty example. Assumes only one freezer module and crew is in that first module. + //if using this in your mod, you need to cleanly store and look-up the freezer module for the + //crewmember and instantiate a DFWrapper.DeepFreezer for that particular module first. + DFWrapper.DeepFreezer freezer = new DFWrapper.DeepFreezer(deepfreezers[0]); + freezer.beginThawKerbal(frzncrewmbr.CrewName); + } + GUILayout.EndHorizontal(); + } + } + GUILayout.Label("ThawedCrew:"); + if (deepfreezers[0].part.vessel.GetCrewCount() == 0) + { + GUILayout.Label("NONE"); + } + else + { + foreach (ProtoCrewMember crew in deepfreezers[0].part.vessel.GetVesselCrew()) + { + GUILayout.BeginHorizontal(); + GUILayout.Label(crew.name); + if (GUILayout.Button("Freeze")) + { + //this is a nasty example. Assumes only one freezer module and crew is in that first module. + //if using this in your mod, you need to cleanly store and look-up the freezer module for the + //crewmember and instantiate a DFWrapper.DeepFreezer for that particular module first. + DFWrapper.DeepFreezer freezer = new DFWrapper.DeepFreezer(deepfreezers[0]); + freezer.beginFreezeKerbal(crew); + } + GUILayout.EndHorizontal(); + } + } + + GUILayout.EndVertical(); + GUILayout.EndScrollView(); + GUILayout.EndVertical(); + GUI.DragWindow(); + } + } +} \ No newline at end of file diff --git a/Source/DeepFreeze_APITester/DeepFreeze_APITester/DF_APITester.csproj b/Source/DeepFreeze_APITester/DeepFreeze_APITester/DF_APITester.csproj new file mode 100644 index 0000000..9fb8107 --- /dev/null +++ b/Source/DeepFreeze_APITester/DeepFreeze_APITester/DF_APITester.csproj @@ -0,0 +1,73 @@ + + + + + Debug + AnyCPU + {1E041E3F-A16F-4830-B9E2-B6C118298E75} + Library + Properties + DF_APITester + DF_APITester + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\Assembly-CSharp.dll + + + + + + + + + ..\..\..\UnityEngine.dll + + + + + + + + + + set /p KSP_DIR=<"$(ProjectDir)ksp_dir.txt" + +xcopy "$(TargetPath)" "$(SolutionDir)..\GameData\REPOSoftTech\$(ProjectName)\Plugins\" /Y + +xcopy "$(TargetDir)$(ProjectName).pdb" "$(SolutionDir)..\GameData\REPOSoftTech\$(ProjectName)\Plugins\" /Y + +cd "$(TargetDir)" +"C:\Program Files (x86)\mono\bin\mono.exe" "C:\Program Files (x86)\mono\lib\mono\4.5\pdb2mdb.exe" "$(TargetFileName)" +xcopy "$(TargetDir)$(ProjectName).dll.mdb" "$(SolutionDir)..\GameData\REPOSoftTech\$(ProjectName)\Plugins\" /Y + + +xcopy /E /Y "$(SolutionDir)..\GameData\REPOSoftTech\DF_APITester" "%25KSP_DIR%25\GameData\REPOSoftTech\DF_APITester" + + + \ No newline at end of file diff --git a/Source/DeepFreeze_APITester/DeepFreeze_APITester/Properties/AssemblyInfo.cs b/Source/DeepFreeze_APITester/DeepFreeze_APITester/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..35bc6e7 --- /dev/null +++ b/Source/DeepFreeze_APITester/DeepFreeze_APITester/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("DF_APITester")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("DF_APITester")] +[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("1e041e3f-a16f-4830-b9e2-b6c118298e75")] + +// 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")] diff --git a/Source/DeepFreeze_APITester/DeepFreeze_APITester/ksp_dir.txt b/Source/DeepFreeze_APITester/DeepFreeze_APITester/ksp_dir.txt new file mode 100644 index 0000000..84ac29e --- /dev/null +++ b/Source/DeepFreeze_APITester/DeepFreeze_APITester/ksp_dir.txt @@ -0,0 +1 @@ +C:\KSP_win 1.0.5 Test \ No newline at end of file diff --git a/Source/DeepFreezerPart.cs b/Source/DeepFreezerPart.cs index 888778d..e681b56 100644 --- a/Source/DeepFreezerPart.cs +++ b/Source/DeepFreezerPart.cs @@ -410,7 +410,7 @@ public List GetConsumedResources() return resources; } - public void Update() + public void Update() { if (Time.timeSinceLevelLoad < 2.0f) // Check not loading level return; @@ -1206,7 +1206,7 @@ public override void OnStart(PartModule.StartState state) Debug.Log("DeepFreezer OnStart"); base.OnStart(state); //Set the GameEvents we are interested in - if ((state != StartState.None || state != StartState.Editor)) + if ((state != StartState.None && state != StartState.Editor)) { GameEvents.onCrewTransferred.Add(this.OnCrewTransferred); GameEvents.onVesselChange.Add(this.OnVesselChange); @@ -1223,63 +1223,65 @@ public override void OnStart(PartModule.StartState state) KSPSpecularShader = listshaders.Find(b => b.name == "KSP/Specular"); // Setup the sounds - mon_beep = gameObject.AddComponent(); - mon_beep.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/mon_beep"); - mon_beep.volume = .2F; - mon_beep.panLevel = 0; - mon_beep.rolloffMode = AudioRolloffMode.Logarithmic; - mon_beep.audio.maxDistance = 10f; - mon_beep.audio.minDistance = 8f; - mon_beep.audio.dopplerLevel = 0f; - mon_beep.audio.panLevel = 0f; - mon_beep.audio.playOnAwake = false; - mon_beep.audio.priority = 255; - mon_beep.Stop(); - flatline = gameObject.AddComponent(); - flatline.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/flatline"); - flatline.volume = 1; - flatline.panLevel = 0; - flatline.rolloffMode = AudioRolloffMode.Linear; - flatline.Stop(); - hatch_lock = gameObject.AddComponent(); - hatch_lock.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/hatch_lock"); - hatch_lock.volume = .5F; - hatch_lock.panLevel = 0; - hatch_lock.rolloffMode = AudioRolloffMode.Linear; - hatch_lock.Stop(); - ice_freeze = gameObject.AddComponent(); - ice_freeze.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/ice_freeze"); - ice_freeze.volume = 1; - ice_freeze.panLevel = 0; - ice_freeze.rolloffMode = AudioRolloffMode.Linear; - ice_freeze.Stop(); - machine_hum = gameObject.AddComponent(); - machine_hum.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/machine_hum"); - machine_hum.volume = .2F; - machine_hum.panLevel = 0; - machine_hum.rolloffMode = AudioRolloffMode.Linear; - machine_hum.Stop(); - ding_ding = gameObject.AddComponent(); - ding_ding.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/ding_ding"); - ding_ding.volume = .4F; - ding_ding.panLevel = 0; - ding_ding.rolloffMode = AudioRolloffMode.Linear; - ding_ding.Stop(); - List databaseAudioFiles = new List(); - databaseAudioFiles = GameDatabase.Instance.databaseAudioFiles; - ext_door = gameObject.AddComponent(); - ext_door.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/externaldoorswitch"); - ext_door.volume = .7F; - ext_door.panLevel = 0; - ext_door.rolloffMode = AudioRolloffMode.Linear; - ext_door.Stop(); - charge_up = gameObject.AddComponent(); - charge_up.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/charge_up"); - charge_up.volume = 1; - charge_up.panLevel = 0; - charge_up.rolloffMode = AudioRolloffMode.Linear; - charge_up.Stop(); - + if ((state != StartState.None && state != StartState.Editor)) + { + mon_beep = gameObject.AddComponent(); + mon_beep.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/mon_beep"); + mon_beep.volume = .2F; + mon_beep.panLevel = 0; + mon_beep.rolloffMode = AudioRolloffMode.Logarithmic; + mon_beep.audio.maxDistance = 10f; + mon_beep.audio.minDistance = 8f; + mon_beep.audio.dopplerLevel = 0f; + mon_beep.audio.panLevel = 0f; + mon_beep.audio.playOnAwake = false; + mon_beep.audio.priority = 255; + mon_beep.Stop(); + flatline = gameObject.AddComponent(); + flatline.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/flatline"); + flatline.volume = 1; + flatline.panLevel = 0; + flatline.rolloffMode = AudioRolloffMode.Linear; + flatline.Stop(); + hatch_lock = gameObject.AddComponent(); + hatch_lock.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/hatch_lock"); + hatch_lock.volume = .5F; + hatch_lock.panLevel = 0; + hatch_lock.rolloffMode = AudioRolloffMode.Linear; + hatch_lock.Stop(); + ice_freeze = gameObject.AddComponent(); + ice_freeze.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/ice_freeze"); + ice_freeze.volume = 1; + ice_freeze.panLevel = 0; + ice_freeze.rolloffMode = AudioRolloffMode.Linear; + ice_freeze.Stop(); + machine_hum = gameObject.AddComponent(); + machine_hum.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/machine_hum"); + machine_hum.volume = .2F; + machine_hum.panLevel = 0; + machine_hum.rolloffMode = AudioRolloffMode.Linear; + machine_hum.Stop(); + ding_ding = gameObject.AddComponent(); + ding_ding.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/ding_ding"); + ding_ding.volume = .4F; + ding_ding.panLevel = 0; + ding_ding.rolloffMode = AudioRolloffMode.Linear; + ding_ding.Stop(); + List databaseAudioFiles = new List(); + databaseAudioFiles = GameDatabase.Instance.databaseAudioFiles; + ext_door = gameObject.AddComponent(); + ext_door.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/externaldoorswitch"); + ext_door.volume = .7F; + ext_door.panLevel = 0; + ext_door.rolloffMode = AudioRolloffMode.Linear; + ext_door.Stop(); + charge_up = gameObject.AddComponent(); + charge_up.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/charge_up"); + charge_up.volume = 1; + charge_up.panLevel = 0; + charge_up.rolloffMode = AudioRolloffMode.Linear; + charge_up.Stop(); + } //If we have an external door (CRY-0300) check if RPM is installed, if not disable the door, otherwise set it's current state (open/closed). if (animationName != string.Empty) { diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs index 1c9f6ee..e8f8451 100644 --- a/Source/Properties/AssemblyInfo.cs +++ b/Source/Properties/AssemblyInfo.cs @@ -31,7 +31,7 @@ // 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("0.20.0.0")] -[assembly: AssemblyFileVersion("0.20.0.0")] +[assembly: AssemblyVersion("0.20.1.0")] +[assembly: AssemblyFileVersion("0.20.1.0")] [assembly: KSPAssembly("DeepFreeze", 0, 20)] [assembly: KSPAssemblyDependency("DFInterface", 0, 4)] \ No newline at end of file diff --git a/TACLSTempFixDLLs.zip b/TACLSTempFixDLLs.zip deleted file mode 100644 index c95236d..0000000 Binary files a/TACLSTempFixDLLs.zip and /dev/null differ