diff --git a/.gitignore b/.gitignore index e63d54f..79f52e4 100644 --- a/.gitignore +++ b/.gitignore @@ -212,3 +212,4 @@ pip-log.txt #Mr Developer .mr.developer.cfg +*.zip diff --git a/DeepFreeze/DeepFreeze.version b/DeepFreeze/DeepFreeze.version deleted file mode 100644 index b369a7a..0000000 --- a/DeepFreeze/DeepFreeze.version +++ /dev/null @@ -1 +0,0 @@ -{"NAME":"DeepFreeze","URL":"http://ksp-avc.cybutek.net/version.php?id=81","DOWNLOAD":"https://github.com/ScottPaladin/DeepFreeze/releases","VERSION":{"MAJOR":0,"MINOR":13,"PATCH":1,"BUILD":0},"KSP_VERSION":{"MAJOR":0,"MINOR":25,"PATCH":0}} \ No newline at end of file diff --git a/DeepFreeze/Parts/CryoFreezer/model000.png b/DeepFreeze/Parts/CryoFreezer/model000.png deleted file mode 100644 index 7bf1b35..0000000 Binary files a/DeepFreeze/Parts/CryoFreezer/model000.png and /dev/null differ diff --git a/DeepFreeze/Parts/CryoFreezer/model001.png b/DeepFreeze/Parts/CryoFreezer/model001.png deleted file mode 100644 index e85c7e0..0000000 Binary files a/DeepFreeze/Parts/CryoFreezer/model001.png and /dev/null differ diff --git a/DeepFreeze/Parts/CryoFreezer/part.cfg b/DeepFreeze/Parts/CryoFreezer/part.cfg deleted file mode 100644 index 88fedb5..0000000 --- a/DeepFreeze/Parts/CryoFreezer/part.cfg +++ /dev/null @@ -1,55 +0,0 @@ -PART -{ -name = cryofreezer -module = Part -author = ScottPaladin - -mesh = model -rescaleFactor = 1 - -node_stack_top = 0.0, 1.830905, 0.0, 0.0, 1.0, 0.0, 2 -node_stack_bottom = 0.0, -1.830905, 0.0, 0.0, 1.0, 0.0, 2 - - -TechRequired = specializedConstruction -entryCost = 12400 -cost = 4500 -category = Utility -subcategory = 0 -title = CRY-2300 Cryonic Freezing Chamber -manufacturer = PaladinLabs -description = Designed for long term storage of up to 10 kerbals. The CRY-2300 uses 5 - -attachRules = 1,0,1,1,0 - -mass = 5.25 -dragModelType = default -maximum_drag = 0.2 -minimum_drag = 0.3 -angularDrag = 2 -crashTolerance = 6 -breakingForce = 200 -breakingTorque = 200 -maxTemp = 2900 - -vesselType = Ship - -RESOURCE -{ - name = Glykerol - amount = 100 - maxAmount = 100 -} -MODULE -{ - name = DeepFreezer - FreezerSize = 10 - IsCrewableWhenFull = true - ChargeRequired = 3000 - ChargeRate = 30 -} -MODULE -{ - name = SimplePartModule - } -} diff --git a/DeepFreeze/Plugins/DeepFreeze.dll b/DeepFreeze/Plugins/DeepFreeze.dll deleted file mode 100644 index 718c26e..0000000 Binary files a/DeepFreeze/Plugins/DeepFreeze.dll and /dev/null differ diff --git a/DeepFreeze/Resources/DF-Resources.cfg b/DeepFreeze/Resources/DF-Resources.cfg deleted file mode 100644 index 18dcb19..0000000 --- a/DeepFreeze/Resources/DF-Resources.cfg +++ /dev/null @@ -1,9 +0,0 @@ -RESOURCE_DEFINITION -{ - name = Glykerol - density = 0.012 - flowMode = ALL_VESSEL - transfer = PUMP - isTweakable = true - unitCost = 0.8 -} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/Asteroid.cfg b/Distribution/GameData/CommunityResourcePack/Asteroid.cfg new file mode 100644 index 0000000..0adce62 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Asteroid.cfg @@ -0,0 +1,132 @@ +@PART[PotatoRoid] +{ + MODULE + { + name = ModuleAsteroidResource + resourceName = Water + presenceChance = 100 + lowRange = 50 + highRange = 75 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = MetallicOre + presenceChance = 80 + lowRange = 50 + highRange = 75 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = Substrate + presenceChance = 80 + lowRange = 50 + highRange = 75 + } + MODULE + { + name = ModuleAsteroidResource + resourceName = Silicates + presenceChance = 80 + lowRange = 50 + highRange = 75 + } + MODULE + { + name = ModuleAsteroidResource + resourceName = Hydrates + presenceChance = 80 + lowRange = 50 + highRange = 75 + } + MODULE + { + name = ModuleAsteroidResource + resourceName = Minerals + presenceChance = 25 + lowRange = 1 + highRange = 10 + } + MODULE + { + name = ModuleAsteroidResource + resourceName = Gypsum + presenceChance = 25 + lowRange = 1 + highRange = 10 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = Karbonite + presenceChance = 25 + lowRange = 50 + highRange = 75 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = Karborundum + presenceChance = 25 + lowRange = 1 + highRange = 10 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = Uraninite + presenceChance = 25 + lowRange = 50 + highRange = 75 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = XenonGas + presenceChance = 80 + lowRange = 1 + highRange = 10 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = ExoticMinerals + presenceChance = 80 + lowRange = 1 + highRange = 30 + } + MODULE + { + name = ModuleAsteroidResource + resourceName = RareMetals + presenceChance = 80 + lowRange = 1 + highRange = 30 + } + + MODULE + { + name = ModuleAsteroidResource + resourceName = ArgonGas + presenceChance = 80 + lowRange = 1 + highRange = 10 + } + + MODULE + { + name = ModuleAsteroidResource + highRange = 95 + lowRange = 80 + presenceChance = 100 + resourceName = Rock + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/CHANGELOG.txt b/Distribution/GameData/CommunityResourcePack/CHANGELOG.txt new file mode 100644 index 0000000..b226dc2 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/CHANGELOG.txt @@ -0,0 +1,175 @@ +1.4.2 - 2020.12.20 +------------------ +KSP 1.11 Compatibility + +1.3.0 - 2019.10.28 +------------------ +KSP 1.8.x Compatibility + +1.2.0 - 2019.08.04 +------------------ +KSP 1.7.x Compatibility + +1.1.0 - 2019.02.05 +------------------ +KSP 1.6.x Compatibility + +1.0.1 - 2018.11.20 +------------------ +Fixed antimatter config name + +1.0.0 - 2018.10.20 +------------------ +KSP 1.5.0 Compatibility +Normalized atmospheric resource harvesting values. + +0.11.0 - 2018.06.22 +------------------ +KSP 1.4.4 Compatibility + +0.10.0 - 2018.03.13 +----------------- +KSP 1.4.1 Compatibility + +0.9.0 - 2018.03.07 +------------------ +KSP 1.4.0 Compatibility + +0.8.1 - 2017.03.06 +------------------ +Fixed an issue with Chinese localization that was causing the game to hang during load. Thanks to everyone that helped with this! +Added Russian translations (Thanks doktorjet) +Corrected density of Silicates/Silicon (Note that while cost/volume are the same, the resources are now ten times heavier) + +0.8.0 - 2017.10.09 +------------------ +KSP 1.3.1 +Various localization updates + +0.7.3 - 2017.09.08 +------------------ +Dependency Updates + +0.7.2 - 2017.08.15 +--------------- +Dependency Updates +Localization Updates +New KSPI Resources + +0.7.1 - KSP 1.3 +------------------ +KSP 1.3 Compatibility +Dependency Updates + +0.6.6 - 2017.02.04 +------------------ +Added common resource Sodium a potential high efficient electric propellant +Added common resource Caesium a rare but dense and highly efficient electric propellant +ResourceLode value set to zero to prevent exploits. + +0.6.5 - (2017.01.01) +-------------------- +Updated asteroid and scanner settings + +0.6.4 - (KSP 1.2.2) +------------------- +Added Decaborane as a resource + +0.6.3 - (KSP 1.2.1) +------------------- +Adjusted cost Fluorine (KSPI-E) to cost LqdFluorine (Realfuels) +Removed double definition of LqdFluorine + +0.6.2 - 2016.10.15 +------------------ +Various KSPI resource updates +Silicate resource distribution added + +0.6.1 - 2016.10.15 +------------------ +Resorted KSPI resources alphabeticly, added abbreviation and Added LqdArgon, LqdFluorine, LqdNitrogen15, LqdOxygen18 + +0.6.0 - (KSP 1.2) +------------------- +Added ARP icon data for RealFuels +Added/Updated distribution data for: +- Antimatter +- Helium3 +- ArgonGas +- XenonGas +- LqdHydrogen +Added several new resources, including: +- HeavyWater +- Deuternium +- Helium4 +- Silicates +- Borate +- ColonySupplies +- RefinedExotics + + +0.5.4 - (KSP 1.1.3) +------------------ +Update for KSP 1.1.3 +Updated cost of Plutonium +Added Lithium6, Carbon, and Monazite +Karborundum is now tweakable, and 4000 funds per unit (versus 400). +The Kerbol Karburundum harvesting zone is back... now go find it :) +Alumina and Monazite are now planetary resources. +Hydrates are a bit more common. +Added Glykerol (curated by DeepFreeze). + +0.5.2 - 2016.05.14 +------------------ +Added Volume and reverted UF4 and ThF4 to original KSPI density & cost +Added Volume property to other resources used by KSPI +Added default volume to other CRP resources + +0.5.1.1 - 2016.04.30 +-------------------- +KSP 1.1.2 compatibility + +0.5.1 - 2016.04.30 +------------------ +KSP 1.1.1 compatibility + +0.5.0 - 2016.03.29 +------------------ +Compatibility with KSP 1.1 +Lowered cost of Supplies, Mulch and Fertilizer + +0.4.9 - 2016.02.01 +------------------ +Added Hydrates as a resource and also to the resource map (represents regolith with captive water) +Added Gypsum (an excellent raw material for fertilizer) as a resource and to the resource map +ExoticMinerals and RareMetals can now be directly harvested + +0.4.8 - 2015.12.08 +------------------ +Added 'IntakeLqd' - an oceanic resource to help with oceanic-only parts. +Modified Asteroid config to include 'Rock' +Added 'Lead' as a resource (same stats as LeadBallast, but visible/tweakable) +Adjusted density of 'Rock' to be more like rock, and less like cotton balls + +0.4.7 - 2015.11.14 +------------------ +Merged MKS and MKS-L resources into CRP + +0.4.6 - 2015.11.09 +------------------ +Added OSE/MKS-L common resources (Dirt, MaterialKits, ExoticMinerals, RareMetals) +KSP 1.0.5 Compatibility + +0.4.5 - 2015.10.16 +------------------ +Fixed density LqdDeteurium and LqdTritium + +0.4.4 - 2015.07.29 +------------------ +Various HSP/flow changes + +0.4.3 - 2015.07.06 +------------------ +Moved the Karborundum band around the sun out a bit. +Various HST configs +Fixed an issue with the cost of RocketParts diff --git a/Distribution/GameData/CommunityResourcePack/CRP.version b/Distribution/GameData/CommunityResourcePack/CRP.version new file mode 100644 index 0000000..904e41a --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/CRP.version @@ -0,0 +1,31 @@ +{ + "NAME":"Community Resource Pack", + "URL":"https://raw.githubusercontent.com/BobPalmer/CommunityResourcePack/master/FOR_RELEASE/GameData/CommunityResourcePack/CRP.version", + "DOWNLOAD":"https://github.com/BobPalmer/CommunityResourcePack/releases", + "GITHUB":{ + "USERNAME":"BobPalmer", + "REPOSITORY":"CommunityResourcePack", + "ALLOW_PRE_RELEASE":false + }, + "VERSION":{ + "MAJOR":1, + "MINOR":4, + "PATCH":2, + "BUILD":0 + }, + "KSP_VERSION":{ + "MAJOR":1, + "MINOR":8, + "PATCH":0 + }, + "KSP_VERSION_MIN":{ + "MAJOR":1, + "MINOR":6, + "PATCH":0 + }, + "KSP_VERSION_MAX":{ + "MAJOR":1, + "MINOR":99, + "PATCH":99 + } + } diff --git a/Distribution/GameData/CommunityResourcePack/CommonResources.cfg b/Distribution/GameData/CommunityResourcePack/CommonResources.cfg new file mode 100644 index 0000000..5e6ecee --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/CommonResources.cfg @@ -0,0 +1,2428 @@ +//****************************** +//* KSP 1.0 Ratified Resources +//****************************** + +//****************************** +//* SECTION 1 CRP/USI Curated +//****************************** + +RESOURCE_DEFINITION +{ + name = Hydrates + displayName = #LOC_CRP_Hydrates_DisplayName + density = 0.00150000000 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.5000000 + color = .25,.25,1 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Gypsum + displayName = #LOC_CRP_Gypsum_DisplayName + density = 0.00550000000 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.01 + color = 1,1,1 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = IntakeLqd //Like IntakeAtm but for oceans + displayName = #LOC_CRP_IntakeLqd_DisplayName //Like IntakeAtm but for oceans + density = 0.0010000000 + hsp = 4183 // specific heat capacity (kJ/tonne-K as units) + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0008 + color = .5,.5,1 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = ColonySupplies + displayName = #LOC_CRP_ColonySupplies_DisplayName + density = 0.001556 + hsp = 500 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 15 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Lead + displayName = #LOC_CRP_Lead_DisplayName + density = 0.01134 + unitCost = 0.067392 + hsp = 128 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = True + isVisible = true + volume = 1 + ksparpicon = RealFuels/Resources/ARPIcons/LeadBallast +} + + +RESOURCE_DEFINITION +{ + name = CarbonDioxide + displayName = #LOC_CRP_CarbonDioxide_DisplayName + density = 0.000001951 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0000028637 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/CarbonDioxide +} + +RESOURCE_DEFINITION +{ + name = Chemicals + displayName = #LOC_CRP_Chemicals_DisplayName + density = 0.00250000000 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 16 + volume = 1 +} + + +RESOURCE_DEFINITION +{ + name = Dirt + displayName = #LOC_CRP_Dirt_DisplayName + density = 0.0016 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.3 + color = 1,1,0 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = ExoticMinerals + displayName = #LOC_CRP_ExoticMinerals_DisplayName + density = 0.0025 + flowMode = ALL_VESSEL + transfer = PUMP + unitCost = 160 + isTweakable = true + isVisible = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/ExoticMatter +} + +RESOURCE_DEFINITION +{ + name = Food + displayName = #LOC_CRP_Food_DisplayName + density = 0.00028102905982906 + hsp = 600 // specific heat capacity (kJ/tonne-K as units) // FIXME total guess + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.238874700854701 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Food +} + +RESOURCE_DEFINITION +{ + name = Supplies + displayName = #LOC_CRP_Supplies_DisplayName + density = 0.001 + flowMode = ALL_VESSEL + transfer = PUMP + unitCost = 2.5 + isTweakable = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Supplies +} + +RESOURCE_DEFINITION +{ + name = Fertilizer + displayName = #LOC_CRP_Fertilizer_DisplayName + density = 0.001 + flowMode = ALL_VESSEL + transfer = PUMP + unitCost = 2 + isTweakable = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Fertilizer +} + +RESOURCE_DEFINITION +{ + name = Mulch + displayName = #LOC_CRP_Mulch_DisplayName + density = 0.001 + flowMode = ALL_VESSEL + transfer = PUMP + unitCost = 0 + isTweakable = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Mulch +} + +RESOURCE_DEFINITION +{ + name = Machinery + displayName = #LOC_CRP_Machinery_DisplayName + density = 0.00378 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + unitCost = 15.8 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = SpecializedParts + displayName = #LOC_CRP_SpecializedParts_DisplayName + density = 0.00378 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + unitCost = 32 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Recyclables + displayName = #LOC_CRP_Recyclables_DisplayName + density = 0.00378 + flowMode = ALL_VESSEL + transfer = PUMP + unitCost = 7 + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Hydrogen + displayName = #LOC_CRP_Hydrogen_DisplayName + density = 0.00000008990 + unitCost = 0.000055836 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Hydrogen +} + +RESOURCE_DEFINITION +{ + name = Karbonite + displayName = #LOC_CRP_Karbonite_DisplayName + density = 0.0025 + unitCost = 0.32 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + color = 1,.5,0 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Karborundum + displayName = #LOC_CRP_Karborundum_DisplayName + density = 0.00580000000 + unitCost = 4000 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + color = 1,0,0 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdCO2 + displayName = #LOC_CRP_LqdCO2_DisplayName + density = 0.00117325 + unitCost = 0.0017247 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + hsp = 850 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/CarbonDioxide +} + +RESOURCE_DEFINITION +{ + name = LqdCO + displayName = #LOC_CRP_LqdCO_DisplayName + density = 0.000790 + unitCost = 0.0021 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + hsp = 2154 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = MaterialKits + displayName = #LOC_CRP_MaterialKits_DisplayName + density = 0.001 + unitCost = 2 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Metals + displayName = #LOC_CRP_Metals_DisplayName + density = 0.0078 + unitCost = 14.24 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Metal +} + +RESOURCE_DEFINITION +{ + name = Minerals + displayName = #LOC_CRP_Minerals_DisplayName + density = 0.00270000000 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.80 + volume = 1 + color = .75,0,1 +} + +RESOURCE_DEFINITION +{ + name = MetallicOre + displayName = #LOC_CRP_MetallicOre_DisplayName + density = 0.00550000000 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 1.76 + color = 0,1,1 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Organics + displayName = #LOC_CRP_Organics_DisplayName + density = 0.001 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.5 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Oxygen + displayName = #LOC_CRP_Oxygen_DisplayName + density = 0.00000141 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.000055836 + color = 0,1,0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Oxygen +} + +RESOURCE_DEFINITION +{ + name = Polymers + displayName = #LOC_CRP_Polymers_DisplayName + density = 0.00104000000 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 8 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = RareMetals + displayName = #LOC_CRP_RareMetals_DisplayName + density = 0.0078 + flowMode = ALL_VESSEL + transfer = PUMP + unitCost = 140 + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = RefinedExotics + displayName = #LOC_CRP_RefinedExotics_DisplayName + density = 0.0052 + flowMode = ALL_VESSEL + transfer = PUMP + unitCost = 250 + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Rock + displayName = #LOC_CRP_Rock_DisplayName + density = 0.0025 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.00001 + volume = 1 +} + + + +RESOURCE_DEFINITION +{ + name = RocketParts + displayName = #LOC_CRP_RocketParts_DisplayName + density = 0.0025 + unitCost = 1.5 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + volume = 5 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/RocketParts +} + +RESOURCE_DEFINITION +{ + name = SpareParts + displayName = #LOC_CRP_SpareParts_DisplayName + density = 0.00378 + flowMode = NO_FLOW + transfer = NONE + isTweakable = true + isVisible = true + unitCost = 12.6 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Substrate + displayName = #LOC_CRP_Substrate_DisplayName + density = 0.0016 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.3 + color = 1,1,0 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Uraninite + displayName = #LOC_CRP_Uraninite_DisplayName + density = 0.0075 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.7 + color = 0,1,0 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Waste + displayName = #LOC_CRP_Waste_DisplayName + density = 0.00075 + hsp = 600 // specific heat capacity (kJ/tonne-K as units) // FIXME total guess + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Waste +} + +RESOURCE_DEFINITION +{ + name = WasteWater + displayName = #LOC_CRP_WasteWater_DisplayName + density = 0.001005 + hsp = 4183 // specific heat capacity (kJ/tonne-K as units) (FIXME same as water) + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/WasteWater +} + +RESOURCE_DEFINITION +{ + name = Water + displayName = #LOC_CRP_Water_DisplayName + density = 0.0010000000 + hsp = 4183 // specific heat capacity (kJ/tonne-K as units) + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0008 + color = .5,.5,1 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Water +} + +//****************************** +//* SECTION 2 NFT Curated +//****************************** + +RESOURCE_DEFINITION +{ + name = ArgonGas // Common electric engine propellant + displayName = #LOC_CRP_ArgonGas_DisplayName // Common electric engine propellant + abbreviation = #LOC_CRP_ArgonGas_Abbreviation + density = 0.00000178400 + unitCost = 0.0105 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + color = 1,0,0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Argon +} + +RESOURCE_DEFINITION +{ + name = Boron + displayName = #LOC_CRP_Boron_DisplayName + abbreviation = #LOC_CRP_Boron_Abbreviation + density = 0.00246000000 + unitCost = 0.851 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = ResourceLode + displayName = #LOC_CRP_ResourceLode_DisplayName + density = 0.005 + flowMode = ALL_VESSEL + transfer = NONE + unitCost = 0 + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = DepletedUranium + displayName = #LOC_CRP_DepletedUranium_DisplayName // Depleted fuel to preserve mass when burned, can be recycled + abbreviation = #LOC_CRP_DepletedUranium_Abbreviation // Depleted fuel to preserve mass when burned, can be recycled + unitCost = 0 + density = 0.01097000000 + flowMode = NO_FLOW + transfer = NONE + isTweakable = true + isVisible = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/DepletedUranium +} + +RESOURCE_DEFINITION +{ + name = EnrichedUranium + displayName = #LOC_CRP_EnrichedUranium_DisplayName // Nuclear fuel + abbreviation = #LOC_CRP_EnrichedUranium_Abbreviation // Nuclear fuel + density = 0.01097000000 + unitCost = 865.0000000 + isTweakable = true + isVisible = true + flowMode = NO_FLOW + transfer = NONE + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/EnrichedUranium +} + +RESOURCE_DEFINITION +{ + name = LqdHydrogen + displayName = #LOC_CRP_LqdHydrogen_DisplayName // General propellant + abbreviation = #LOC_CRP_LqdHydrogen_Abbreviation // General propellant + density = 0.00007085000 + unitCost = 0.0367500 + hsp = 9690 // specific heat capacity (kJ/tonne-K as units) at Crygenic Storage temperature + vsp = 448500 // heat of vapourization (KJ/tonne as units) or 8.97 * 10^5 or 8.97E5? + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/LiquidHydrogen +} + +RESOURCE_DEFINITION +{ + name = StoredCharge + displayName = #LOC_CRP_StoredCharge_DisplayName // Capacitor resource. Translates to Ec + abbreviation = #LOC_CRP_StoredCharge_Abbreviation // Capacitor resource. Translates to Ec + unitCost = 0 + density = 0 + flowMode = NO_FLOW + transfer = NONE + isTweakable = false + isVisible = true + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/StoredCharge +} + +//****************************** +//* SECTION 3 KSPI-E Curated +//****************************** + +RESOURCE_DEFINITION +{ + name = Actinides + abbreviation = #LOC_CRP_Actinides_Abbreviation + displayName = #LOC_CRP_Actinides_DisplayName + density = 0.01097 + flowMode = NO_FLOW + transfer = NONE + isTweakable = false + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Actinides +} + +RESOURCE_DEFINITION +{ + name = Aluminium + abbreviation = #LOC_CRP_Aluminium_Abbreviation + displayName = #LOC_CRP_Aluminium_DisplayName + density = 0.00277 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 1.5 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Aluminium +} + +RESOURCE_DEFINITION +{ + name = Alumina + abbreviation = #LOC_CRP_Alumina_Abbreviation + displayName = #LOC_CRP_Alumina_DisplayName + density = 0.00398 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.5 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Alumina +} + +RESOURCE_DEFINITION +{ + name = Ammonia + abbreviation = #LOC_CRP_Ammonia_Abbreviation + displayName = #LOC_CRP_Ammonia_DisplayName + density = 0.000000769 + unitCost = 0.00015 + hsp = 2175 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Antimatter + abbreviation = #LOC_CRP_Antimatter_Abbreviation + displayName = #LOC_CRP_Antimatter_DisplayName + density = 0.000000001 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = false + isVisible = true + unitCost = 100 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/AntiMatter +} + +RESOURCE_DEFINITION +{ + name = AntiHydrogen + displayName = #LOC_CRP_AntiHydrogen_DisplayName + abbreviation = #LOC_CRP_AntiHydrogen_Abbreviation + density = 0.000086 // LqdHydrogen: 0.00007085000 + unitCost = 8600000 // LqdHydrogen: 0.0367500 + hsp = 9690 // for now similar to Liquid Hydrogen + vsp = 448500 // for now similar to Liquid Hydrogen + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdArgon + abbreviation = #LOC_CRP_LqdArgon_Abbreviation + displayName = #LOC_CRP_LqdArgon_DisplayName + density = 0.0013954 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + unitCost = 1.4 + isTweakable = true + isVisible = true + hsp = 1078 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Borate + abbreviation = #LOC_CRP_Borate_Abbreviation + displayName = #LOC_CRP_Borate_DisplayName + density = 0.00173 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.02 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Caesium + abbreviation = #LOC_CRP_Caesium_Abbreviation + displayName = #LOC_CRP_Caesium_DisplayName + density = 0.00193 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 77 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Calcium + abbreviation = #LOC_CRP_Calcium_Abbreviation + displayName = #LOC_CRP_Calcium_DisplayName + density = 0.00155 + unitCost = 0.00015 + hsp = 650 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = CarbonMonoxide + abbreviation = #LOC_CRP_CarbonMonoxide_Abbreviation + displayName = #LOC_CRP_CarbonMonoxide_DisplayName + density = 0.00000125 + unitCost = 0.00000332 + hsp = 1046 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Carbon + abbreviation = #LOC_CRP_Carbon_Abbreviation + displayName = #LOC_CRP_Carbon_DisplayName + density = 0.0021 + unitCost = 0.0 + hsp = 710 + flowMode = NO_FLOW + transfer = NONE + isTweakable = false + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = ChargedParticles + abbreviation = #LOC_CRP_ChargedParticles_Abbreviation + displayName = #LOC_CRP_ChargedParticles_DisplayName + density = 0 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = false + isVisible = true + unitCost = 0 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/ChargedParticles +} + +RESOURCE_DEFINITION +{ + name = Chlorine + abbreviation = #LOC_CRP_Chlorine_Abbreviation + displayName = #LOC_CRP_Chlorine_DisplayName + density = 0.0032 + unitCost = 0.00015 + hsp = 3394 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = CompressedAir + abbreviation = #LOC_CRP_CompressedAir_Abbreviation + displayName = #LOC_CRP_CompressedAir_DisplayName + density = 0.000001283 + unitCost = 0.00004 + hsp = 2175 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Decaborane + abbreviation = #LOC_CRP_Decaborane_Abbreviation + displayName = #LOC_CRP_Decaborane_DisplayName + density = 0.00094 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.345 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Deuterium + abbreviation = #LOC_CRP_Deuterium_Abbreviation + displayName = #LOC_CRP_Deuterium_DisplayName + density = 0.000000180 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.00028 + hsp = 6950 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdDeuterium + abbreviation = #LOC_CRP_LqdDeuterium_Abbreviation + displayName = #LOC_CRP_LqdDeuterium_DisplayName + density = 0.0001624 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.256 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = DepletedFuel + abbreviation = #LOC_CRP_DepletedFuel_Abbreviation + displayName = #LOC_CRP_DepletedFuel_DisplayName + density = 0.01097 + flowMode = NO_FLOW + transfer = NONE + isTweakable = false + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/DepletedFuel +} + +RESOURCE_DEFINITION +{ + name = ExoticMatter + abbreviation = #LOC_CRP_ExoticMatter_Abbreviation + displayName = #LOC_CRP_ExoticMatter_DisplayName + density = 0 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = false + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/ExoticMatter +} + + +RESOURCE_DEFINITION +{ + name = Fluorine + abbreviation = #LOC_CRP_Fluorine_Abbreviation + displayName = #LOC_CRP_Fluorine_DisplayName + density = 0.000001696 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.010176 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Fluorite + abbreviation = #LOC_CRP_Fluorite_Abbreviation + displayName = #LOC_CRP_Fluorite_DisplayName + density = 0.0032 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 9.35 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = HeavyWater + abbreviation = #LOC_CRP_HeavyWater_Abbreviation + displayName = #LOC_CRP_HeavyWater_DisplayName + density = 0.001107 + hsp = 4183 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 1 + color = .3,.3,1 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = IntakeAtm + abbreviation = #LOC_CRP_IntakeAtm_Abbreviation + displayName = #LOC_CRP_IntakeAtm_DisplayName + density = 0.005 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = false + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/IntakeAtm +} + +RESOURCE_DEFINITION +{ + name = KryptonGas + abbreviation = #LOC_CRP_KryptonGas_Abbreviation + displayName = #LOC_CRP_KryptonGas_DisplayName + density = 0.000003749 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0068 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdKrypton + abbreviation = #LOC_CRP_LqdKrypton_Abbreviation + displayName = #LOC_CRP_LqdKrypton_DisplayName + density = 0.002413 + unitCost = 1.0298 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = NeonGas + abbreviation = #LOC_CRP_NeonGas_Abbreviation + displayName = #LOC_CRP_NeonGas_DisplayName + density = 0.0000009002 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0016 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdNeon + abbreviation = #LOC_CRP_LqdNeon_Abbreviation + displayName = #LOC_CRP_LqdNeon_DisplayName + density = 0.001207 + unitCost = 2.1453 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Lithium + abbreviation = #LOC_CRP_Lithium_Abbreviation + displayName = #LOC_CRP_Lithium_DisplayName + density = 0.000534 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.6075 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Lithium +} + +RESOURCE_DEFINITION +{ + name = Lithium6 + abbreviation = #LOC_CRP_Lithium6_Abbreviation + displayName = #LOC_CRP_Lithium6_DisplayName + density = 0.000458 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 4 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LithiumHydride + abbreviation = #LOC_CRP_LithiumHydride_Abbreviation + displayName = #LOC_CRP_LithiumHydride_DisplayName + title = #LOC_CRP_LithiumHydride_Title + density = 0.00078 + unitCost = 0.4 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LithiumDeuteride + abbreviation = #LOC_CRP_LithiumDeuteride_Abbreviation + displayName = #LOC_CRP_LithiumDeuteride_DisplayName + title = #LOC_CRP_LithiumDeuteride_Title + density = 0.00082 + unitCost = 5 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdAmmonia + abbreviation = #LOC_CRP_LqdAmmonia_Abbreviation + displayName = #LOC_CRP_LqdAmmonia_DisplayName + density = 0.0007021 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.142 + hsp= 5170 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/LqdAmmonia +} + +RESOURCE_DEFINITION +{ + name = Helium3 + abbreviation = #LOC_CRP_Helium3_Abbreviation + displayName = #LOC_CRP_Helium3_DisplayName + density = 0.000000125 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.11127 + hsp = 4560 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Helium-3 +} + +RESOURCE_DEFINITION +{ + name = LqdHe3 + abbreviation = #LOC_CRP_LqdHe3_Abbreviation + displayName = #LOC_CRP_LqdHe3_DisplayName + density = 0.000059 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 52.52 + hsp = 4560 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Helium4 + abbreviation = #LOC_CRP_Helium4_Abbreviation + displayName = #LOC_CRP_Helium4_DisplayName + density = 0.0000001786 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0000133 + hsp = 5188 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdHelium + abbreviation = #LOC_CRP_LqdHelium_Abbreviation + displayName = #LOC_CRP_LqdHelium_DisplayName + density = 0.0001786 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0133 + hsp = 4560 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/LqdHelium +} + +RESOURCE_DEFINITION +{ + name = Nitratine + abbreviation = #LOC_CRP_Nitratine_Abbreviation + displayName = #LOC_CRP_Nitratine_DisplayName + title = #LOC_CRP_Nitratine_Title + density = 0.0024 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.001 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Hexaborane + abbreviation = #LOC_CRP_Hexaborane_Abbreviation + displayName = #LOC_CRP_Hexaborane_DisplayName + density = 0.000670 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + unitCost = 0.25 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdNitrogen + abbreviation = #LOC_CRP_LqdNitrogen_Abbreviation + displayName = #LOC_CRP_LqdNitrogen_DisplayName + density = 0.000824907 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.0008240 + hsp = 2040 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdNitrogen15 + abbreviation = #LOC_CRP_LqdNitrogen15_Abbreviation + displayName = #LOC_CRP_LqdNitrogen15_DisplayName + density = 0.0008838 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.08240 // About 100 times cost LqdNitrogen + hsp = 2040 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Magnesium + abbreviation = #LOC_CRP_Magnesium_Abbreviation + displayName = #LOC_CRP_Magnesium_DisplayName + density = 0.001738 + unitCost = 0.00015 + hsp = 1020 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Megajoules + abbreviation = #LOC_CRP_Megajoules_Abbreviation + displayName = #LOC_CRP_Megajoules_DisplayName + density = 0 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = false + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Megajoules +} + +RESOURCE_DEFINITION +{ + name = Monazite + abbreviation = #LOC_CRP_Monazite_Abbreviation + displayName = #LOC_CRP_Monazite_DisplayName + density = 0.005 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.1 + color = 0,0.8,0.2 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdOxygen18 + abbreviation = #LOC_CRP_LqdOxygen18_Abbreviation + displayName = #LOC_CRP_LqdOxygen18_DisplayName + density = 0.001284 + unitCost = 0.6 // about 13 times cost of LqdOxygen + hsp = 918 // specific heat capacity (kJ/tonne-K as units) // recalc, mols are for O2 on wiki + vsp = 213000 // heat of vapourization (KJ/tonne as units) + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Salt + abbreviation = #LOC_CRP_Salt_Abbreviation + displayName = #LOC_CRP_Salt_DisplayName + density = 0.002 + unitCost = 0.002 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Sodium + abbreviation = #LOC_CRP_Sodium_Abbreviation + displayName = #LOC_CRP_Sodium_DisplayName + density = 0.000968 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 1.4 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = SolidHydrogen + displayName = #LOC_CRP_SolidHydrogen_DisplayName + abbreviation = #LOC_CRP_SolidHydrogen_Abbreviation + density = 0.000086 + unitCost = 0.0446 + hsp = 9690 // for now similar to Liquid Hydrogen + vsp = 448500 // for now similar to Liquid Hydrogen + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = true + isVisible = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = PolyvinylChloride + abbreviation = #LOC_CRP_PolyvinylChloride_Abbreviation + displayName = #LOC_CRP_PolyvinylChloride_DisplayName + density = 0.00149 + hsp = 7981 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 1 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Plutonium-238 + abbreviation = #LOC_CRP_Plutonium-238_Abbreviation + displayName = #LOC_CRP_Plutonium-238_DisplayName + density = 0.019816 + flowMode = NO_FLOW + transfer = NONE + isTweakable = true + isVisible = true + unitCost = 4000 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Plutonium-238 +} + +RESOURCE_DEFINITION +{ + name = Potassium + abbreviation = #LOC_CRP_Potassium_Abbreviation + displayName = #LOC_CRP_Potassium_DisplayName + density = 0.000862 + unitCost = 0.00015 + hsp = 750 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Regolith + abbreviation = #LOC_CRP_Regolith_Abbreviation + displayName = #LOC_CRP_Regolith_DisplayName + density = 0.002 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = UF4 + abbreviation = #LOC_CRP_UF4_Abbreviation + displayName = #LOC_CRP_UF4_DisplayName + density = 0.00670 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = true + isVisible = true + unitCost = 72 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/UF4 +} + +RESOURCE_DEFINITION +{ + name = Silicates + abbreviation = #LOC_CRP_Silicates_Abbreviation + displayName = #LOC_CRP_Silicates_DisplayName + density = 0.0025 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.01 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Silicon + abbreviation = #LOC_CRP_Silicon_Abbreviation + displayName = #LOC_CRP_Silicon_DisplayName + density = 0.002329 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.02 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = SolarWind + abbreviation = #LOC_CRP_SolarWind_Abbreviation + displayName = #LOC_CRP_SolarWind_DisplayName + density = 0.00000124725 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 0.001 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Spodumene + abbreviation = #LOC_CRP_Spodumene_Abbreviation + displayName = #LOC_CRP_Spodumene_DisplayName + density = 0.0031 + unitCost = 0.174 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = Sulphur + abbreviation = #LOC_CRP_Sulphur_Abbreviation + displayName = #LOC_CRP_Sulphur_DisplayName + density = 0.00207 + unitCost = 0.00015 + hsp = 730 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = ThermalPower + abbreviation = #LOC_CRP_ThermalPower_Abbreviation + displayName = #LOC_CRP_ThermalPower_DisplayName + density = 0 + unitCost = 0 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = false + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/ThermalPower +} + +RESOURCE_DEFINITION +{ + name = Thorium + abbreviation = #LOC_CRP_Thorium_Abbreviation + displayName = #LOC_CRP_Thorium_DisplayName + density = 0.0117 + unitCost = 46.8 + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = ThF4 + abbreviation = #LOC_CRP_ThF4_Abbreviation + displayName = #LOC_CRP_ThF4_DisplayName + density = 0.0063 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = true + isVisible = true + unitCost = 18 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/ThF4 +} + +RESOURCE_DEFINITION +{ + name = Tritium + abbreviation = #LOC_CRP_Tritium_Abbreviation + displayName = #LOC_CRP_Tritium_DisplayName + density = 0.0000002705 + unitCost = 0.016 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = LqdTritium + abbreviation = #LOC_CRP_LqdTritium_Abbreviation + displayName = #LOC_CRP_LqdTritium_DisplayName + density = 0.000320 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 18.8 + hsp = 9690 + volume = 1 +} + +RESOURCE_DEFINITION +{ + name = UraniumNitride + abbreviation = #LOC_CRP_UraniumNitride_Abbreviation + displayName = #LOC_CRP_UraniumNitride_DisplayName + density = 0.0143 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + isVisible = true + unitCost = 158 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/UraniumNitride +} + +RESOURCE_DEFINITION +{ + name = VacuumPlasma + abbreviation = #LOC_CRP_VacuumPlasma_Abbreviation + displayName = #LOC_CRP_VacuumPlasma_DisplayName + density = 0.005 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = false + isVisible = true + unitCost = 0 + volume = 1 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/VacuumPlasma +} + + +RESOURCE_DEFINITION +{ + name = WasteHeat + abbreviation = #LOC_CRP_WasteHeat_Abbreviation + displayName = #LOC_CRP_WasteHeat_DisplayName + density = 0 + flowMode = ALL_VESSEL + transfer = NONE + isTweakable = false + isVisible = true + unitCost = 0 + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/WasteHeat +} + + RESOURCE_DEFINITION + { + name = LqdXenon + abbreviation = #LOC_CRP_LqdXenon_Abbreviation + displayName = #LOC_CRP_LqdXenon_DisplayName + density = 0.002953 + unitCost = 118.12 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +//****************************** +//* SECTION 4 RealFuels Curated +//****************************** + +RESOURCE_DEFINITION +{ + name = Aerozine50 + displayName = #LOC_CRP_Aerozine50_DisplayName + density = 0.0009 + unitCost = 1.35 + hsp = 2970.1 // specific heat capacity (kJ/tonne-K as units) // http://www.gentoogeek.org/steves_world/hypergol_properties.pdf + // hydrazine: http://webbook.nist.gov/cgi/cbook.cgi?ID=C302012&Units=SI&Mask=1A8F&Type=JANAFL&Plot=on#JANAFL - 3120.6 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Aerozine +} + +RESOURCE_DEFINITION +{ + name = AK20 + displayName = #LOC_CRP_AK20_DisplayName + density = 0.001499 + unitCost = 0.2998 + hsp = 1720 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html for nitric acid, copied to AKx + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/AK20 +} + +RESOURCE_DEFINITION +{ + name = AK27 + displayName = #LOC_CRP_AK27_DisplayName + density = 0.001494 + unitCost = 0.2988 + hsp = 1720 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html for nitric acid, copied to AKx + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/AK27 +} + +RESOURCE_DEFINITION +{ + name = Aniline + displayName = #LOC_CRP_Aniline_DisplayName + density = 0.00102 + unitCost = 0.5213333 + hsp = 2180 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html for aniline, copied to others. Note http://pubs.acs.org/doi/abs/10.1021/ja01147a515 disagrees, says Aniline is ~2100. + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Aniline +} + +RESOURCE_DEFINITION +{ + name = AvGas + displayName = #LOC_CRP_AvGas_DisplayName + density = 0.000719 + unitCost = 0.12 + hsp = 2220 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/AvGas +} + +RESOURCE_DEFINITION +{ + name = CaveaB + displayName = #LOC_CRP_CaveaB_DisplayName + density = 0.001501 + unitCost = 0.33022 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/CaveaB +} + +RESOURCE_DEFINITION +{ + name = ClF3 + displayName = #LOC_CRP_ClF3_DisplayName + density = 0.00177 + unitCost = 10.62 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/ClF3 +} + +RESOURCE_DEFINITION +{ + name = ClF5 + displayName = #LOC_CRP_ClF5_DisplayName + density = 0.0019 + unitCost = 15.2 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/ClF5 +} + +RESOURCE_DEFINITION +{ + name = Diborane + displayName = #LOC_CRP_Diborane_DisplayName + density = 0.000421 + unitCost = 4.21 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Diborane +} + +RESOURCE_DEFINITION +{ + name = Ethane + displayName = #LOC_CRP_Ethane_DisplayName + density = 0.000544 + unitCost = 0.09248 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Ethane +} + +RESOURCE_DEFINITION +{ + name = Ethanol + displayName = #LOC_CRP_Ethanol_DisplayName + density = 0.000789 + unitCost = 0.12624 + hsp = 2720 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Ethanol75 +} + +RESOURCE_DEFINITION +{ + name = Ethanol75 + displayName = #LOC_CRP_Ethanol75_DisplayName + density = 0.00084175 + unitCost = 0.12624 + hsp = 3156 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Ethanol75 +} + +RESOURCE_DEFINITION +{ + name = Ethanol90 + displayName = #LOC_CRP_Ethanol90_DisplayName + density = 0.0008101 + unitCost = 0.12624 + hsp = 2901 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Ethanol75 +} + +RESOURCE_DEFINITION +{ + name = Ethylene + displayName = #LOC_CRP_Ethylene_DisplayName + density = 0.000568 + unitCost = 0.09656 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Ethylene +} + +RESOURCE_DEFINITION +{ + name = FLOX30 + displayName = #LOC_CRP_FLOX30_DisplayName + density = 0.0012517 + unitCost = 2.403264 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/FLOX30 +} + +RESOURCE_DEFINITION +{ + name = FLOX70 + displayName = #LOC_CRP_FLOX70_DisplayName + density = 0.0013993 + unitCost = 6.184906 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/FLOX70 +} + +RESOURCE_DEFINITION +{ + name = FLOX88 + displayName = #LOC_CRP_FLOX88_DisplayName + density = 0.0014657 + unitCost = 8.134635 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/FLOX88 +} + +RESOURCE_DEFINITION +{ + name = Furfuryl + displayName = #LOC_CRP_Furfuryl_DisplayName + density = 0.00113 + unitCost = 0.1808 + hsp = 2096 // specific heat capacity (kJ/tonne-K as units) // http://pubs.acs.org/doi/abs/10.1021/ja01147a515 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Furfuryl +} + +RESOURCE_DEFINITION +{ + name = Helium + displayName = #LOC_CRP_Helium_DisplayName + density = 0.0000001786 + unitCost = 0.0000091 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Helium +} + +RESOURCE_DEFINITION +{ + name = HNIW + displayName = #LOC_CRP_HNIW_DisplayName + density = 0.002044 + unitCost = 0.4504976 + hsp = 920 // FIXME, total guess but based on 'standardized' solids and the stock SolidFuel hsp. + flowMode = NO_FLOW + transfer = NONE + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/HNIW +} + +RESOURCE_DEFINITION +{ + name = HTP + displayName = #LOC_CRP_HTP_DisplayName + density = 0.001431 + unitCost = 2.1465 + hsp = 2721 // specific heat capacity (kJ/tonne-K as units) // http://www.h2o2.com/technical-library/physical-chemical-properties/thermodynamic-properties/default.aspx?pid=36&name=Heat-Capacity + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/HTP +} + +RESOURCE_DEFINITION +{ + name = HTPB + displayName = #LOC_CRP_HTPB_DisplayName + density = 0.00177 + unitCost = 1.8585 + hsp = 920 // FIXME, total guess but based on 'standardized' solids and the stock SolidFuel hsp. + flowMode = NO_FLOW + transfer = NONE + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/HTPB +} + +RESOURCE_DEFINITION +{ + name = Hydrazine + displayName = #LOC_CRP_Hydrazine_DisplayName + density = 0.001004 + unitCost = 2.008 + hsp = 3120.6 // specific heat capacity (kJ/tonne-K as units) // http://webbook.nist.gov/cgi/cbook.cgi?ID=C302012&Units=SI&Mask=1A8F&Type=JANAFL&Plot=on#JANAFL + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Hydrazine +} + +RESOURCE_DEFINITION +{ + name = Hydyne + displayName = #LOC_CRP_Hydyne_DisplayName + density = 0.00086 + unitCost = 0.688 + hsp = 2625 // specific heat capacity (kJ/tonne-K as units) // UDMH + DETA. UDMH is above, DETA is 2466 per wiki. Mix was 60:40, so... + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Hydyne +} + +RESOURCE_DEFINITION +{ + name = IRFNA-III + displayName = #LOC_CRP_IRFNA-III_DisplayName + density = 0.001658 + unitCost = 0.34818 + hsp = 1720 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html for nitric acid, copied to AKx + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/IRFNA-III +} + +RESOURCE_DEFINITION +{ + name = IRFNA-IV + displayName = #LOC_CRP_IRFNA-IV_DisplayName + density = 0.001995 + unitCost = 0.399 + hsp = 1720 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html for nitric acid, copied to AKx + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/IRFNA-IV +} + +RESOURCE_DEFINITION +{ + name = IWFNA + displayName = #LOC_CRP_IWFNA_DisplayName + density = 0.001513 + unitCost = 0.31773 + hsp = 1720 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html for nitric acid, copied to AKx + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/IWFNA +} + +RESOURCE_DEFINITION +{ + name = Kerosene + displayName = #LOC_CRP_Kerosene_DisplayName + density = 0.00082 + unitCost = 0.041 + hsp = 2010 // specific heat capacity (kJ/tonne-K as units) + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Kerosene +} + +RESOURCE_DEFINITION +{ + name = LeadBallast + displayName = #LOC_CRP_LeadBallast_DisplayName + density = 0.01134 + unitCost = 0.067392 + hsp = 128 // specific heat capacity (kJ/tonne-K as units) // http://hyperphysics.phy-astr.gsu.edu/hbase/tables/sphtt.html + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = false + ksparpicon = RealFuels/Resources/ARPIcons/LeadBallast +} + +RESOURCE_DEFINITION +{ + name = LqdFluorine + displayName = #LOC_CRP_LqdFluorine_DisplayName + density = 0.001505 + unitCost = 9.03 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/LqdFluorine +} + +RESOURCE_DEFINITION +{ + name = LqdMethane + displayName = #LOC_CRP_LqdMethane_DisplayName + density = 0.00042561 + unitCost = 0.45 + hsp = 3348.8 // http://neutronresearch.com/parch/1995/01/199501006440.pdf + vsp = 510000 // http://www.engineeringtoolbox.com/methane-d_1420.html + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/LqdMethane +} + +RESOURCE_DEFINITION +{ + name = LqdOxygen + displayName = #LOC_CRP_LqdOxygen_DisplayName + density = 0.001141 + unitCost = 0.04564 + hsp = 918 // specific heat capacity (kJ/tonne-K as units) // recalc, mols are for O2 on wiki + vsp = 213000 // heat of vapourization (KJ/tonne as units) + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/LiquidOxygen +} + +RESOURCE_DEFINITION +{ + name = Methane + displayName = #LOC_CRP_Methane_DisplayName + density = 0.000000717 + unitCost = 0.0018642 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Methane +} + +RESOURCE_DEFINITION +{ + name = Methanol + displayName = #LOC_CRP_Methanol_DisplayName + density = 0.0007918 + unitCost = 0.126688 + hsp = 2510 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Methanol +} + +RESOURCE_DEFINITION +{ + name = MMH + displayName = #LOC_CRP_MMH_DisplayName + density = 0.00088 + unitCost = 1.748 + hsp = 2928.8 // specific heat capacity (kJ/tonne-K as units) + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/MMH +} + +RESOURCE_DEFINITION +{ + name = MON1 + displayName = #LOC_CRP_MON1_DisplayName + density = 0.001429 + unitCost = 0.21435 + hsp = 1513.46 // NTO + N2O + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/MON1 +} + +RESOURCE_DEFINITION +{ + name = MON3 + displayName = #LOC_CRP_MON3_DisplayName + density = 0.001423 + unitCost = 0.21345 + hsp = 1497.2 // NTO + N2O + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/MON3 +} + +RESOURCE_DEFINITION +{ + name = MON10 + displayName = #LOC_CRP_MON10_DisplayName + density = 0.001407 + unitCost = 0.23919 + hsp = 1440.24 // NTO + N2O + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/MON10 +} + +RESOURCE_DEFINITION +{ + name = MON15 + displayName = #LOC_CRP_MON15_DisplayName + density = 0.001397 + unitCost = 0.23749 + hsp = 1399.56 // NTO + N2O + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/MON15 +} + +RESOURCE_DEFINITION +{ + name = MON20 + displayName = #LOC_CRP_MON20_DisplayName + density = 0.00138 + unitCost = 0.2484 + hsp = 1358.88 // NTO + N2O + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/MON20 +} + +RESOURCE_DEFINITION +{ + name = MON25 + displayName = #LOC_CRP_MON25_DisplayName + density = 0.00138 + unitCost = 0.2484 + hsp = 1318.2 // NTO + N2O + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true +} + +RESOURCE_DEFINITION +{ + name = NGNC + displayName = #LOC_CRP_NGNC_DisplayName + density = 0.0016 + unitCost = 0.01 + hsp = 920 // FIXME, total guess but based on 'standardized' solids and the stock SolidFuel hsp. + flowMode = NO_FLOW + transfer = NONE + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/NGNC +} + +RESOURCE_DEFINITION +{ + name = N2F4 + displayName = #LOC_CRP_N2F4_DisplayName + density = 0.001604 + unitCost = 24.06 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/N2F4 +} + +RESOURCE_DEFINITION +{ + name = Nitrogen + displayName = #LOC_CRP_Nitrogen_DisplayName + density = 0.000001251 + unitCost = 0.00005 + hsp = 1039 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/nitrogen-d_977.html + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Nitrogen +} + +RESOURCE_DEFINITION +{ + name = NitrousOxide + displayName = #LOC_CRP_NitrousOxide_DisplayName + density = 0.00000196 + unitCost = 0.000392 + hsp = 708 // https://books.google.com/books?id=6-VdBgAAQBAJ&lpg=PA337&ots=drEom6Tx9D&dq=nitrous%20oxide%20liquid%20heat%20capacity&pg=PA110#v=onepage&q&f=false + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/NitrousOxide +} + +RESOURCE_DEFINITION +{ + name = NTO + displayName = #LOC_CRP_NTO_DisplayName + density = 0.00145 + unitCost = 0.2175 + hsp = 1521.6 // specific heat capacity (kJ/tonne-K as units) // http://webbook.nist.gov/cgi/cbook.cgi?ID=C10544726&Type=JANAFL&Plot=on#JANAFL + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/N2O4 +} + +RESOURCE_DEFINITION +{ + name = OF2 + displayName = #LOC_CRP_OF2_DisplayName + density = 0.0019 + unitCost = 28.5 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/OF2 +} + +RESOURCE_DEFINITION +{ + name = PBAN + displayName = #LOC_CRP_PBAN_DisplayName + density = 0.001772 + unitCost = 1.593 + hsp = 920 // FIXME, total guess but based on 'standardized' solids and the stock SolidFuel hsp. + flowMode = NO_FLOW + transfer = NONE + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/PBAN +} + +RESOURCE_DEFINITION +{ + name = Pentaborane + displayName = #LOC_CRP_Pentaborane_DisplayName + density = 0.000618 + unitCost = 6.18 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Pentaborane +} + +RESOURCE_DEFINITION +{ + name = PSPC + displayName = #LOC_CRP_PSPC_DisplayName + density = 0.00174 + unitCost = 0.01 + hsp = 920 // FIXME, total guess but based on 'standardized' solids and the stock SolidFuel hsp. + flowMode = NO_FLOW + transfer = NONE + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/PSPC +} + +RESOURCE_DEFINITION +{ + name = Syntin + displayName = #LOC_CRP_Syntin_DisplayName + density = 0.000851 + unitCost = 0.4255 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/Syntin +} + +RESOURCE_DEFINITION +{ + name = TEATEB + displayName = #LOC_CRP_TEATEB_DisplayName + density = 0.00070031 + unitCost = 2.80124 + flowMode = NO_FLOW + transfer = NONE + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/TEATEB +} + +RESOURCE_DEFINITION +{ + name = Tonka250 + displayName = #LOC_CRP_Tonka250_DisplayName + density = 0.000873 + unitCost = 0.4365 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Tonka250 +} + +RESOURCE_DEFINITION +{ + name = Tonka500 + displayName = #LOC_CRP_Tonka500_DisplayName + density = 0.000811 + unitCost = 0.44605 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/Tonka500 +} + +RESOURCE_DEFINITION +{ + name = UDMH + displayName = #LOC_CRP_UDMH_DisplayName + density = 0.000791 + unitCost = 0.791 + hsp = 2729.6 // specific heat capacity (kJ/tonne-K as units) // http://webbook.nist.gov/cgi/cbook.cgi?ID=C10544726&Type=JANAFL&Plot=on#JANAFL + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = TriggerTech/KSPAlternateResourcePanel/Icons/UDMH +} + +RESOURCE_DEFINITION +{ + name = UH25 + displayName = UH25 + density = 0.000829 + unitCost = 1.03625 + hsp = 2850 // specific heat capacity (kJ/tonne-K as units) // guesstimate based on Hydrazine and UDMH and AZ50 + flowMode = STACK_PRIORITY_SEARCH + transfer = PUMP + isTweakable = True + isVisible = true + ksparpicon = RealFuels/Resources/ARPIcons/UH25 +} + +//****************************** +//* SECTION 5 DeepFreeze Curated +//****************************** + +RESOURCE_DEFINITION +{ + name = Glykerol + displayName = #LOC_CRP_Glykerol_DisplayName + density = 0.012 + unitCost = 2 + hsp = 2430 // specific heat capacity (kJ/tonne-K as units) // http://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html + flowMode = ALL_VESSEL + transfer = PUMP + isTweakable = true + ksparpicon = REPOSoftTech/DeepFreeze/Icons/Glykerol + ksparpdisplayvalueas = Units +} + +//**************************************** +//* SECTION 6 Wild Blue Industries Curated +//**************************************** + +RESOURCE_DEFINITION +{ + name = FusionPellets + displayName = #LOC_CRP_FusionPellets_DisplayName + density = 0.000216 + unitCost = 150 + flowMode = STAGE_PRIORITY_FLOW + transfer = PUMP + isTweakable = true + volume = 1 +} + +//****************************** +//* END +//****************************** diff --git a/Distribution/GameData/CommunityResourcePack/License_CC.txt b/Distribution/GameData/CommunityResourcePack/License_CC.txt new file mode 100644 index 0000000..d60efe4 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/License_CC.txt @@ -0,0 +1,437 @@ +Attribution-NonCommercial-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/Distribution/GameData/CommunityResourcePack/Localization/de-de.cfg b/Distribution/GameData/CommunityResourcePack/Localization/de-de.cfg new file mode 100644 index 0000000..24ed621 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/de-de.cfg @@ -0,0 +1,245 @@ +Localization +{ + de-de + { + //USI + #LOC_CRP_Hydrates_DisplayName = Hydrate + #LOC_CRP_Gypsum_DisplayName = Gips + #LOC_CRP_IntakeLqd_DisplayName = Einlassflüssigkeit + #LOC_CRP_ColonySupplies_DisplayName = Kolonievorräte + #LOC_CRP_Lead_DisplayName = Blei + #LOC_CRP_CarbonDioxide_DisplayName = Kohlenstoffdioxid + #LOC_CRP_Chemicals_DisplayName = Chemikalien + #LOC_CRP_Dirt_DisplayName = Erde + #LOC_CRP_ExoticMinerals_DisplayName = Exotische Mineralien + #LOC_CRP_Food_DisplayName = Nahrungsmittel + #LOC_CRP_Supplies_DisplayName = Vorräte + #LOC_CRP_Fertilizer_DisplayName = Düngemittel + #LOC_CRP_Mulch_DisplayName = Mulch + #LOC_CRP_Machinery_DisplayName = Maschinerie + #LOC_CRP_SpecializedParts_DisplayName = Spezialteile + #LOC_CRP_Recyclables_DisplayName = Wertstoffe + #LOC_CRP_Hydrogen_DisplayName = Wasserstoff + #LOC_CRP_Karbonite_DisplayName = Karbonit + #LOC_CRP_Karborundum_DisplayName = Karborund + #LOC_CRP_LqdCO2_DisplayName = LCO2 + #LOC_CRP_LqdCO_DisplayName = LCO + #LOC_CRP_MaterialKits_DisplayName = MaterialKits + #LOC_CRP_Metals_DisplayName = Metalle + #LOC_CRP_Minerals_DisplayName = Mineralien + #LOC_CRP_MetallicOre_DisplayName = Metallisches Erz + #LOC_CRP_Organics_DisplayName = Organische Stoffe + #LOC_CRP_Oxygen_DisplayName = Sauerstoff + #LOC_CRP_Polymers_DisplayName = Polymere + #LOC_CRP_RareMetals_DisplayName = Seltene Metalle + #LOC_CRP_RefinedExotics_DisplayName = Raffinierte Exotische Stoffe + #LOC_CRP_Rock_DisplayName = Stein + #LOC_CRP_RocketParts_DisplayName = Raketenteile + #LOC_CRP_SpareParts_DisplayName = Ersatzteile + #LOC_CRP_Substrate_DisplayName = Substrate + #LOC_CRP_Uraninite_DisplayName = Uraninit + #LOC_CRP_Waste_DisplayName = Abfall + #LOC_CRP_WasteWater_DisplayName = Abwasser + #LOC_CRP_Water_DisplayName = Wasser + //NFT + #LOC_CRP_ArgonGas_DisplayName = Argon + #LOC_CRP_ArgonGas_Abbreviation = Ar + #LOC_CRP_Boron_DisplayName = Bor + #LOC_CRP_Boron_Abbreviation = Bo + #LOC_CRP_ResourceLode_DisplayName = Rohstoffarder + #LOC_CRP_EnrichedUranium_DisplayName = Angereichertes Uran + #LOC_CRP_EnrichedUranium_Abbreviation = AngerU + #LOC_CRP_DepletedUranium_DisplayName = Abgereichertes Uran + #LOC_CRP_DepletedUranium_Abbreviation = AbgerU + #LOC_CRP_LqdHydrogen_DisplayName = Flüssiger Wasserstoff + #LOC_CRP_LqdHydrogen_Abbreviation = LH2 + #LOC_CRP_StoredCharge_DisplayName = Gespeicherte Ladung + #LOC_CRP_StoredCharge_Abbreviation = Q + //KSPI-E + #LOC_CRP_Actinides_DisplayName = Actinoide + #LOC_CRP_Actinides_Abbreviation = Act + #LOC_CRP_Aluminium_DisplayName = Aluminium + #LOC_CRP_Aluminium_Abbreviation = Al + #LOC_CRP_Alumina_DisplayName = Aluminiumoxid + #LOC_CRP_Alumina_Abbreviation = Al2O3 + #LOC_CRP_Ammonia_DisplayName = Ammoniak + #LOC_CRP_Ammonia_Abbreviation = NH3 + #LOC_CRP_Antimatter_DisplayName = Antimaterie + #LOC_CRP_Antimatter_Abbreviation = AM + #LOC_CRP_AntiHydrogen_DisplayName = Antiwasserstoff + #LOC_CRP_AntiHydrogen_Abbreviation = AH + #LOC_CRP_LqdArgon_DisplayName = LArgon + #LOC_CRP_LqdArgon_Abbreviation = LAr + #LOC_CRP_Borate_DisplayName = Borat + #LOC_CRP_Borate_Abbreviation = Br + #LOC_CRP_Caesium_DisplayName = Cäsium + #LOC_CRP_Caesium_Abbreviation = Cs + #LOC_CRP_CarbonMonoxide_DisplayName = Kohlenstoffmonoxid + #LOC_CRP_CarbonMonoxide_Abbreviation = CO + #LOC_CRP_Carbon_DisplayName = Kohlenstoff + #LOC_CRP_Carbon_Abbreviation = C + #LOC_CRP_ChargedParticles_DisplayName = Geladene Teilchen + #LOC_CRP_ChargedParticles_Abbreviation = GT + #LOC_CRP_Chlorine_DisplayName = Chlor + #LOC_CRP_Chlorine_Abbreviation = Cl + #LOC_CRP_CompressedAir_DisplayName = Druckluft + #LOC_CRP_CompressedAir_Abbreviation = Luft + #LOC_CRP_Decaborane_DisplayName = Decaboran + #LOC_CRP_Decaborane_Abbreviation = B10H14 + #LOC_CRP_Deuterium_DisplayName = Deuterium + #LOC_CRP_Deuterium_Abbreviation = D + #LOC_CRP_LqdDeuterium_DisplayName = LDeuterium + #LOC_CRP_LqdDeuterium_Abbreviation = LD + #LOC_CRP_DepletedFuel_DisplayName = Abgereicherter Treibstoff + #LOC_CRP_DepletedFuel_Abbreviation = AbgeT + #LOC_CRP_ExoticMatter_DisplayName = Exotische Materie + #LOC_CRP_ExoticMatter_Abbreviation = ExM + #LOC_CRP_FusionPellets_DisplayName = Fusionspellets + #LOC_CRP_Fluorine_DisplayName = Fluor + #LOC_CRP_Fluorine_Abbreviation = F + #LOC_CRP_Fluorite_DisplayName = Fluorit + #LOC_CRP_Fluorite_Abbreviation = CaF2 + #LOC_CRP_HeavyWater_DisplayName = Schweres Wasser + #LOC_CRP_HeavyWater_Abbreviation = D20 + #LOC_CRP_IntakeAtm_DisplayName = Ansauggas + #LOC_CRP_IntakeAtm_Abbreviation = Ansaug + #LOC_CRP_KryptonGas_DisplayName = Kryptongas + #LOC_CRP_KryptonGas_Abbreviation = Kr + #LOC_CRP_LqdKrypton_DisplayName = LKrypton + #LOC_CRP_LqdKrypton_Abbreviation = LKr + #LOC_CRP_NeonGas_DisplayName = Neon + #LOC_CRP_NeonGas_Abbreviation = Ne + #LOC_CRP_LqdNeon_DisplayName = LNeon + #LOC_CRP_LqdNeon_Abbreviation = LNe + #LOC_CRP_Lithium_DisplayName = Lithium7 + #LOC_CRP_Lithium_Abbreviation = Li7 + #LOC_CRP_Lithium6_DisplayName = Lithium6 + #LOC_CRP_Lithium6_Abbreviation = Li6 + #LOC_CRP_LithiumHydride_DisplayName = Lithiumhydrid + #LOC_CRP_LithiumHydride_Abbreviation = Li7H + #LOC_CRP_LithiumDeuteride_DisplayName = Lithiumdeuterid + #LOC_CRP_LithiumDeuteride_Abbreviation = Li6D + #LOC_CRP_LqdAmmonia_DisplayName = LAmmoniak + #LOC_CRP_LqdAmmonia_Abbreviation = NH3 + #LOC_CRP_Helium3_DisplayName = Helium3 + #LOC_CRP_Helium3_Abbreviation = He3 + #LOC_CRP_LqdHe3_DisplayName = LHe3 + #LOC_CRP_LqdHe3_Abbreviation = LHe3 + #LOC_CRP_Helium4_DisplayName = Helium4 + #LOC_CRP_Helium4_Abbreviation = He4 + #LOC_CRP_LqdHelium_DisplayName = LHelium + #LOC_CRP_LqdHelium_Abbreviation = LHe4 + #LOC_CRP_Nitratine_DisplayName = Nitronatrit + #LOC_CRP_Nitratine_Title = Nitronatrit + #LOC_CRP_Hexaborane_DisplayName = Hexaboran + #LOC_CRP_Hexaborane_Abbreviation = HxBo + #LOC_CRP_LqdNitrogen_DisplayName = Flüssiger Stickstoff + #LOC_CRP_LqdNitrogen_Abbreviation = LN14 + #LOC_CRP_LqdNitrogen15_DisplayName = Flüssiger Stickstoff + #LOC_CRP_LqdNitrogen15_Abbreviation = LN15 + #LOC_CRP_Megajoules_DisplayName = Megajoule + #LOC_CRP_Megajoules_Abbreviation = MJ + #LOC_CRP_Monazite_DisplayName = Monazit + #LOC_CRP_Monazite_Abbreviation = Monz + #LOC_CRP_LqdOxygen18_DisplayName = Flüssiger Sauerstoff18 + #LOC_CRP_LqdOxygen18_Abbreviation = LO18 + #LOC_CRP_Salt_DisplayName = Salz + #LOC_CRP_Salt_Abbreviation = Salz + #LOC_CRP_Sodium_DisplayName = Natrium + #LOC_CRP_Sodium_Abbreviation = Na + #LOC_CRP_SolidHydrogen_DisplayName = Fester Wasserstoff + #LOC_CRP_SolidHydrogen_Abbreviation = SH + #LOC_CRP_PolyvinylChloride_DisplayName = Polyvinylchlorid + #LOC_CRP_PolyvinylChloride_Abbreviation = PVC + #LOC_CRP_Plutonium-238_DisplayName = Plutonium-238 + #LOC_CRP_Plutonium-238_Abbreviation = Pu238 + #LOC_CRP_Regolith_DisplayName = Regolith + #LOC_CRP_Regolith_Abbreviation = R + #LOC_CRP_UF4_DisplayName = Uran(IV)-fluorid + #LOC_CRP_UF4_Abbreviation = UF4 + #LOC_CRP_Silicates_DisplayName = Silicate + #LOC_CRP_Silicates_Abbreviation = Silicate + #LOC_CRP_Silicon_DisplayName = Silizium + #LOC_CRP_Silicon_Abbreviation = Si + #LOC_CRP_Spodumene_DisplayName = Spodumen + #LOC_CRP_Spodumene_Abbreviation = LiAl + #LOC_CRP_SolarWind_DisplayName = Sonnenwind + #LOC_CRP_SolarWind_Abbreviation = SW + #LOC_CRP_ThermalPower_DisplayName = Wärmekraft + #LOC_CRP_ThermalPower_Abbreviation = WärmeK + #LOC_CRP_Thorium_DisplayName = Thorium + #LOC_CRP_ThF4_DisplayName = ThF4 + #LOC_CRP_ThF4_Abbreviation = ThF4 + #LOC_CRP_Tritium_DisplayName = Tritium + #LOC_CRP_Tritium_Abbreviation = T + #LOC_CRP_LqdTritium_DisplayName = Flüssiges Tritium + #LOC_CRP_LqdTritium_Abbreviation = LT + #LOC_CRP_UraniumNitride_DisplayName = UranNitrid + #LOC_CRP_UraniumNitride_Abbreviation = UN + #LOC_CRP_VacuumPlasma_DisplayName = VakuumPlasma + #LOC_CRP_VacuumPlasma_Abbreviation = VP + #LOC_CRP_WasteHeat_DisplayName = Abwärme + #LOC_CRP_WasteHeat_Abbreviation = AW + #LOC_CRP_LqdXenon_DisplayName = Flüssiges Xenon + #LOC_CRP_LqdXenon_Abbreviation = LXe + //RealFuels + #LOC_CRP_Aerozine50_DisplayName = Aerozin 50 + #LOC_CRP_AK20_DisplayName = AK20 + #LOC_CRP_AK27_DisplayName = AK27 + #LOC_CRP_Aniline_DisplayName = Anilin + #LOC_CRP_AvGas_DisplayName = AvGas + #LOC_CRP_CaveaB_DisplayName = CaveaB + #LOC_CRP_ClF3_DisplayName = ClF3 + #LOC_CRP_ClF5_DisplayName = ClF5 + #LOC_CRP_Diborane_DisplayName = Diboran + #LOC_CRP_Ethane_DisplayName = Ethan + #LOC_CRP_Ethanol_DisplayName = Ethanol + #LOC_CRP_Ethanol75_DisplayName = Ethanol75 + #LOC_CRP_Ethanol90_DisplayName = Ethanol90 + #LOC_CRP_Ethylene_DisplayName = Ethylen + #LOC_CRP_FLOX30_DisplayName = FLOX30 + #LOC_CRP_FLOX70_DisplayName = FLOX70 + #LOC_CRP_FLOX88_DisplayName = FLOX88 + #LOC_CRP_Furfuryl_DisplayName = Furfuryl + #LOC_CRP_Helium_DisplayName = Helium + #LOC_CRP_HNIW_DisplayName = HNIW + #LOC_CRP_HTP_DisplayName = HTP + #LOC_CRP_HTPB_DisplayName = HTPB + #LOC_CRP_Hydrazine_DisplayName = Hydrazin + #LOC_CRP_Hydyne_DisplayName = Hydyne + #LOC_CRP_IRFNA-III_DisplayName = IRFNA-III + #LOC_CRP_IRFNA-IV_DisplayName = IRFNA-IV + #LOC_CRP_IWFNA_DisplayName = IWFNA + #LOC_CRP_Kerosene_DisplayName = Kerosin + #LOC_CRP_LeadBallast_DisplayName = Bleiballast + #LOC_CRP_LqdFluorine_DisplayName = LFluor + #LOC_CRP_LqdMethane_DisplayName = LMethan + #LOC_CRP_LqdOxygen_DisplayName = LSauerstoff + #LOC_CRP_Methane_DisplayName = Methan + #LOC_CRP_Methanol_DisplayName = Methanol + #LOC_CRP_MMH_DisplayName = MMH + #LOC_CRP_MON1_DisplayName = MON1 + #LOC_CRP_MON3_DisplayName = MON3 + #LOC_CRP_MON10_DisplayName = MON10 + #LOC_CRP_MON15_DisplayName = MON15 + #LOC_CRP_MON20_DisplayName = MON20 + #LOC_CRP_MON25_DisplayName = MON25 + #LOC_CRP_NGNC_DisplayName = NGNC + #LOC_CRP_N2F4_DisplayName = N2F4 + #LOC_CRP_Nitrogen_DisplayName = Stickstoff + #LOC_CRP_NitrousOxide_DisplayName = Lachgas + #LOC_CRP_NTO_DisplayName = NTO + #LOC_CRP_OF2_DisplayName = OF2 + #LOC_CRP_PBAN_DisplayName = PBAN + #LOC_CRP_Pentaborane_DisplayName = Pentaboran + #LOC_CRP_PSPC_DisplayName = PSPC + #LOC_CRP_Syntin_DisplayName = Syntin + #LOC_CRP_TEATEB_DisplayName = TEATEB + #LOC_CRP_Tonka250_DisplayName = Tonka250 + #LOC_CRP_Tonka500_DisplayName = Tonka500 + #LOC_CRP_UDMH_DisplayName = UDMH + #LOC_CRP_UH25_DisplayName = UH25 + //DeepFreeze + #LOC_CRP_Glykerol_DisplayName = Glycerin + } +} diff --git a/Distribution/GameData/CommunityResourcePack/Localization/en-us.cfg b/Distribution/GameData/CommunityResourcePack/Localization/en-us.cfg new file mode 100644 index 0000000..89bc020 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/en-us.cfg @@ -0,0 +1,251 @@ +Localization +{ + en-us + { + //USI + #LOC_CRP_Hydrates_DisplayName = Hydrates + #LOC_CRP_Gypsum_DisplayName = Gypsum + #LOC_CRP_IntakeLqd_DisplayName = IntakeLqd + #LOC_CRP_ColonySupplies_DisplayName = ColonySupplies + #LOC_CRP_Lead_DisplayName = Lead + #LOC_CRP_CarbonDioxide_DisplayName = CarbonDioxide + #LOC_CRP_Chemicals_DisplayName = Chemicals + #LOC_CRP_Dirt_DisplayName = Dirt + #LOC_CRP_ExoticMinerals_DisplayName = ExoticMinerals + #LOC_CRP_Food_DisplayName = Food + #LOC_CRP_Supplies_DisplayName = Supplies + #LOC_CRP_Fertilizer_DisplayName = Fertilizer + #LOC_CRP_Mulch_DisplayName = Mulch + #LOC_CRP_Machinery_DisplayName = Machinery + #LOC_CRP_SpecializedParts_DisplayName = SpecializedParts + #LOC_CRP_Recyclables_DisplayName = Recyclables + #LOC_CRP_Hydrogen_DisplayName = Hydrogen + #LOC_CRP_Karbonite_DisplayName = Karbonite + #LOC_CRP_Karborundum_DisplayName = Karborundum + #LOC_CRP_LqdCO2_DisplayName = LqdCO2 + #LOC_CRP_LqdCO_DisplayName = LqdCO + #LOC_CRP_MaterialKits_DisplayName = MaterialKits + #LOC_CRP_Metals_DisplayName = Metals + #LOC_CRP_Minerals_DisplayName = Minerals + #LOC_CRP_MetallicOre_DisplayName = MetallicOre + #LOC_CRP_Organics_DisplayName = Organics + #LOC_CRP_Oxygen_DisplayName = Oxygen + #LOC_CRP_Polymers_DisplayName = Polymers + #LOC_CRP_RareMetals_DisplayName = RareMetals + #LOC_CRP_RefinedExotics_DisplayName = RefinedExotics + #LOC_CRP_Rock_DisplayName = Rock + #LOC_CRP_RocketParts_DisplayName = RocketParts + #LOC_CRP_SpareParts_DisplayName = SpareParts + #LOC_CRP_Substrate_DisplayName = Substrate + #LOC_CRP_Uraninite_DisplayName = Uraninite + #LOC_CRP_Waste_DisplayName = Waste + #LOC_CRP_WasteWater_DisplayName = WasteWater + #LOC_CRP_Water_DisplayName = Water + //NFT + #LOC_CRP_ArgonGas_DisplayName = Argon Gas + #LOC_CRP_ArgonGas_Abbreviation = Ar + #LOC_CRP_Boron_DisplayName = Boron + #LOC_CRP_Boron_Abbreviation = Bo + #LOC_CRP_ResourceLode_DisplayName = ResourceLode + #LOC_CRP_EnrichedUranium_DisplayName = Enriched Uranium + #LOC_CRP_EnrichedUranium_Abbreviation = EnrU + #LOC_CRP_DepletedUranium_DisplayName = Depleted Uranium + #LOC_CRP_DepletedUranium_Abbreviation = DepU + #LOC_CRP_LqdHydrogen_DisplayName = Liquid Hydrogen + #LOC_CRP_LqdHydrogen_Abbreviation = LH2 + #LOC_CRP_StoredCharge_DisplayName = Stored Charge + #LOC_CRP_StoredCharge_Abbreviation = SC + //KSPI-E + #LOC_CRP_Actinides_DisplayName = Actinides + #LOC_CRP_Actinides_Abbreviation = Act + #LOC_CRP_Aluminium_DisplayName = Aluminium + #LOC_CRP_Aluminium_Abbreviation = Al + #LOC_CRP_Alumina_DisplayName = Alumina + #LOC_CRP_Alumina_Abbreviation = Aia + #LOC_CRP_Ammonia_DisplayName = Ammonia + #LOC_CRP_Ammonia_Abbreviation = NH3 + #LOC_CRP_Antimatter_DisplayName = Antimatter + #LOC_CRP_Antimatter_Abbreviation = AM + #LOC_CRP_AntiHydrogen_DisplayName = Anti Hydrogen + #LOC_CRP_AntiHydrogen_Abbreviation = AH + #LOC_CRP_LqdArgon_DisplayName = LqdArgon + #LOC_CRP_LqdArgon_Abbreviation = Ar + #LOC_CRP_Borate_DisplayName = Borate + #LOC_CRP_Borate_Abbreviation = Br + #LOC_CRP_Caesium_DisplayName = Caesium + #LOC_CRP_Caesium_Abbreviation = Cs + #LOC_CRP_Calcium_Abbreviation = Ca + #LOC_CRP_Calcium_DisplayName = Calcium + #LOC_CRP_CarbonMonoxide_DisplayName = CarbonMonoxide + #LOC_CRP_CarbonMonoxide_Abbreviation = CO + #LOC_CRP_Carbon_DisplayName = Carbon + #LOC_CRP_Carbon_Abbreviation = C + #LOC_CRP_ChargedParticles_DisplayName = ChargedParticles + #LOC_CRP_ChargedParticles_Abbreviation = CP + #LOC_CRP_Chlorine_DisplayName = Chlorine + #LOC_CRP_Chlorine_Abbreviation = Cl + #LOC_CRP_CompressedAir_DisplayName = Compressed Air + #LOC_CRP_CompressedAir_Abbreviation = Air + #LOC_CRP_Decaborane_DisplayName = Decaborane + #LOC_CRP_Decaborane_Abbreviation = DeBo + #LOC_CRP_Deuterium_DisplayName = Deuterium + #LOC_CRP_Deuterium_Abbreviation = D + #LOC_CRP_LqdDeuterium_DisplayName = LqdDeuterium + #LOC_CRP_LqdDeuterium_Abbreviation = D + #LOC_CRP_DepletedFuel_DisplayName = DepletedFuel + #LOC_CRP_DepletedFuel_Abbreviation = DepF + #LOC_CRP_ExoticMatter_DisplayName = ExoticMatter + #LOC_CRP_ExoticMatter_Abbreviation = EcM + #LOC_CRP_FusionPellets_DisplayName = FusionPellets + #LOC_CRP_FusionPellets_Abbreviation = FP + #LOC_CRP_Fluorine_DisplayName = Fluorine + #LOC_CRP_Fluorine_Abbreviation = F + #LOC_CRP_Fluorite_DisplayName = Fluorite + #LOC_CRP_Fluorite_Abbreviation = CaF2 + #LOC_CRP_HeavyWater_DisplayName = HeavyWater + #LOC_CRP_HeavyWater_Abbreviation = D20 + #LOC_CRP_IntakeAtm_DisplayName = IntakeAtm + #LOC_CRP_IntakeAtm_Abbreviation = IntA + #LOC_CRP_KryptonGas_DisplayName = KryptonGas + #LOC_CRP_KryptonGas_Abbreviation = Kr + #LOC_CRP_LqdKrypton_DisplayName = LqdKrypton + #LOC_CRP_LqdKrypton_Abbreviation = Kr + #LOC_CRP_NeonGas_DisplayName = NeonGas + #LOC_CRP_NeonGas_Abbreviation = Ne + #LOC_CRP_LqdNeon_DisplayName = LqdNeon + #LOC_CRP_LqdNeon_Abbreviation = Ne + #LOC_CRP_Lithium_DisplayName = Lithium + #LOC_CRP_Lithium_Abbreviation = Li7 + #LOC_CRP_Lithium6_DisplayName = Lithium6 + #LOC_CRP_Lithium6_Abbreviation = Li6 + #LOC_CRP_LithiumHydride_DisplayName = LithiumHydride + #LOC_CRP_LithiumHydride_Abbreviation = Li7H + #LOC_CRP_LithiumDeuteride_DisplayName = LithiumDeuteride + #LOC_CRP_LithiumDeuteride_Abbreviation = Li6D + #LOC_CRP_LqdAmmonia_DisplayName = LqdAmmonia + #LOC_CRP_LqdAmmonia_Abbreviation = NH3 + #LOC_CRP_Helium3_DisplayName = Helium3 + #LOC_CRP_Helium3_Abbreviation = He3 + #LOC_CRP_LqdHe3_DisplayName = LqdHe3 + #LOC_CRP_LqdHe3_Abbreviation = He3 + #LOC_CRP_Helium4_DisplayName = Helium4 + #LOC_CRP_Helium4_Abbreviation = He4 + #LOC_CRP_LqdHelium_DisplayName = LqdHelium + #LOC_CRP_LqdHelium_Abbreviation = He4 + #LOC_CRP_Nitratine_DisplayName = Nitratine + #LOC_CRP_Nitratine_Abbreviation = Nit + #LOC_CRP_Hexaborane_DisplayName = Hexaborane + #LOC_CRP_Hexaborane_Abbreviation = HxBo + #LOC_CRP_LqdNitrogen_DisplayName = LqdNitrogen + #LOC_CRP_LqdNitrogen_Abbreviation = N14 + #LOC_CRP_LqdNitrogen15_DisplayName = LqdNitrogen15 + #LOC_CRP_LqdNitrogen15_Abbreviation = N15 + #LOC_CRP_Megajoules_DisplayName = Megajoules + #LOC_CRP_Megajoules_Abbreviation = Meg3 + #LOC_CRP_Monazite_DisplayName = Monazite + #LOC_CRP_Monazite_Abbreviation = Monz + #LOC_CRP_LqdOxygen18_DisplayName = LqdOxygen18 + #LOC_CRP_LqdOxygen18_Abbreviation = O18 + #LOC_CRP_Salt_DisplayName = Salt + #LOC_CRP_Salt_Abbreviation = Salt + #LOC_CRP_Sodium_DisplayName = Sodium + #LOC_CRP_Sodium_Abbreviation = Na + #LOC_CRP_Sulphur_DisplayName = Sulphur + #LOC_CRP_Sulphur_Abbreviation = S + #LOC_CRP_SolidHydrogen_DisplayName = SolidHydrogen + #LOC_CRP_SolidHydrogen_Abbreviation = SH + #LOC_CRP_PolyvinylChloride_DisplayName = PolyvinylChloride + #LOC_CRP_PolyvinylChloride_Abbreviation = PVC + #LOC_CRP_Plutonium-238_DisplayName = Plutonium-238 + #LOC_CRP_Plutonium-238_Abbreviation = Pu238 + #LOC_CRP_Regolith_DisplayName = Regolith + #LOC_CRP_Regolith_Abbreviation = R + #LOC_CRP_UF4_DisplayName = UF4 + #LOC_CRP_UF4_Abbreviation = UF4 + #LOC_CRP_Silicates_DisplayName = Silicates + #LOC_CRP_Silicates_Abbreviation = Silica + #LOC_CRP_Silicon_DisplayName = Silicon + #LOC_CRP_Silicon_Abbreviation = Si + #LOC_CRP_Spodumene_DisplayName = Spodumene + #LOC_CRP_Spodumene_Abbreviation = LiAl + #LOC_CRP_SolarWind_DisplayName = SolarWind + #LOC_CRP_SolarWind_Abbreviation = SW + #LOC_CRP_ThermalPower_DisplayName = ThermalPower + #LOC_CRP_ThermalPower_Abbreviation = ThP + #LOC_CRP_Thorium_DisplayName = Thorium + #LOC_CRP_Thorium_Abbreviation = Th + #LOC_CRP_ThF4_DisplayName = ThF4 + #LOC_CRP_ThF4_Abbreviation = ThF4 + #LOC_CRP_Tritium_DisplayName = Tritium + #LOC_CRP_Tritium_Abbreviation = T + #LOC_CRP_LqdTritium_DisplayName = LqdTritium + #LOC_CRP_LqdTritium_Abbreviation = T + #LOC_CRP_UraniumNitride_DisplayName = UraniumNitride + #LOC_CRP_UraniumNitride_Abbreviation = UN + #LOC_CRP_VacuumPlasma_DisplayName = VacuumPlasma + #LOC_CRP_VacuumPlasma_Abbreviation = VP + #LOC_CRP_WasteHeat_DisplayName = WasteHeat + #LOC_CRP_WasteHeat_Abbreviation = WH + #LOC_CRP_LqdXenon_DisplayName = LqdXenon + #LOC_CRP_LqdXenon_Abbreviation = Xe + //RealFuels + #LOC_CRP_Aerozine50_DisplayName = Aerozine50 + #LOC_CRP_AK20_DisplayName = AK20 + #LOC_CRP_AK27_DisplayName = AK27 + #LOC_CRP_Aniline_DisplayName = Aniline + #LOC_CRP_AvGas_DisplayName = AvGas + #LOC_CRP_CaveaB_DisplayName = CaveaB + #LOC_CRP_ClF3_DisplayName = ClF3 + #LOC_CRP_ClF5_DisplayName = ClF5 + #LOC_CRP_Diborane_DisplayName = Diborane + #LOC_CRP_Ethane_DisplayName = Ethane + #LOC_CRP_Ethanol_DisplayName = Ethanol + #LOC_CRP_Ethanol75_DisplayName = Ethanol75 + #LOC_CRP_Ethanol90_DisplayName = Ethanol90 + #LOC_CRP_Ethylene_DisplayName = Ethylene + #LOC_CRP_FLOX30_DisplayName = FLOX30 + #LOC_CRP_FLOX70_DisplayName = FLOX70 + #LOC_CRP_FLOX88_DisplayName = FLOX88 + #LOC_CRP_Furfuryl_DisplayName = Furfuryl + #LOC_CRP_Helium_DisplayName = Helium + #LOC_CRP_HNIW_DisplayName = HNIW + #LOC_CRP_HTP_DisplayName = HTP + #LOC_CRP_HTPB_DisplayName = HTPB + #LOC_CRP_Hydrazine_DisplayName = Hydrazine + #LOC_CRP_Hydyne_DisplayName = Hydyne + #LOC_CRP_IRFNA-III_DisplayName = IRFNA-III + #LOC_CRP_IRFNA-IV_DisplayName = IRFNA-IV + #LOC_CRP_IWFNA_DisplayName = IWFNA + #LOC_CRP_Kerosene_DisplayName = Kerosene + #LOC_CRP_LeadBallast_DisplayName = LeadBallast + #LOC_CRP_LqdFluorine_DisplayName = LqdFluorine + #LOC_CRP_LqdMethane_DisplayName = LqdMethane + #LOC_CRP_LqdOxygen_DisplayName = LqdOxygen + #LOC_CRP_Methane_DisplayName = Methane + #LOC_CRP_Methanol_DisplayName = Methanol + #LOC_CRP_MMH_DisplayName = MMH + #LOC_CRP_MON1_DisplayName = MON1 + #LOC_CRP_MON3_DisplayName = MON3 + #LOC_CRP_MON10_DisplayName = MON10 + #LOC_CRP_MON15_DisplayName = MON15 + #LOC_CRP_MON20_DisplayName = MON20 + #LOC_CRP_MON25_DisplayName = MON25 + #LOC_CRP_NGNC_DisplayName = NGNC + #LOC_CRP_N2F4_DisplayName = N2F4 + #LOC_CRP_Nitrogen_DisplayName = Nitrogen + #LOC_CRP_NitrousOxide_DisplayName = NitrousOxide + #LOC_CRP_NTO_DisplayName = NTO + #LOC_CRP_OF2_DisplayName = OF2 + #LOC_CRP_PBAN_DisplayName = PBAN + #LOC_CRP_Pentaborane_DisplayName = Pentaborane + #LOC_CRP_PSPC_DisplayName = PSPC + #LOC_CRP_Syntin_DisplayName = Syntin + #LOC_CRP_TEATEB_DisplayName = TEATEB + #LOC_CRP_Tonka250_DisplayName = Tonka250 + #LOC_CRP_Tonka500_DisplayName = Tonka500 + #LOC_CRP_UDMH_DisplayName = UDMH + #LOC_CRP_UH25_DisplayName = UH25 + //DeepFreeze + #LOC_CRP_Glykerol_DisplayName = Glykerol + } +} diff --git a/Distribution/GameData/CommunityResourcePack/Localization/es-es.cfg b/Distribution/GameData/CommunityResourcePack/Localization/es-es.cfg new file mode 100644 index 0000000..ac67d8c --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/es-es.cfg @@ -0,0 +1,251 @@ +Localization +{ + es-es + { + //USI + #LOC_CRP_Hydrates_DisplayName = Hidratos + #LOC_CRP_Gypsum_DisplayName = Yeso + #LOC_CRP_IntakeLqd_DisplayName = Ingreso Lqd + #LOC_CRP_ColonySupplies_DisplayName = Suministros coloniales + #LOC_CRP_Lead_DisplayName = Plomo + #LOC_CRP_CarbonDioxide_DisplayName = Dióxido de carbono + #LOC_CRP_Chemicals_DisplayName = Productos químicos + #LOC_CRP_Dirt_DisplayName = Suciedad + #LOC_CRP_ExoticMinerals_DisplayName = Minerales exóticos + #LOC_CRP_Food_DisplayName = Comida + #LOC_CRP_Supplies_DisplayName = Suministros + #LOC_CRP_Fertilizer_DisplayName = Fertilizante + #LOC_CRP_Mulch_DisplayName = Mantillo + #LOC_CRP_Machinery_DisplayName = Maquinaria + #LOC_CRP_SpecializedParts_DisplayName = Piezas especializadas + #LOC_CRP_Recyclables_DisplayName = Reciclables + #LOC_CRP_Hydrogen_DisplayName = Hidrógeno + #LOC_CRP_Karbonite_DisplayName = Karbonita + #LOC_CRP_Karborundum_DisplayName = Karborundum + #LOC_CRP_LqdCO2_DisplayName = LqdCO2 + #LOC_CRP_LqdCO_DisplayName = LqdCO + #LOC_CRP_MaterialKits_DisplayName = Kits de materiales + #LOC_CRP_Metals_DisplayName = Metales + #LOC_CRP_Minerals_DisplayName = Minerales + #LOC_CRP_MetallicOre_DisplayName = Mineral metálico + #LOC_CRP_Organics_DisplayName = Orgánicos + #LOC_CRP_Oxygen_DisplayName = Oxígeno + #LOC_CRP_Polymers_DisplayName = Polímeros + #LOC_CRP_RareMetals_DisplayName = Metales raros + #LOC_CRP_RefinedExotics_DisplayName = Exóticos refinados + #LOC_CRP_Rock_DisplayName = Roca + #LOC_CRP_RocketParts_DisplayName = Piezas de cohetes + #LOC_CRP_SpareParts_DisplayName = Repuestos + #LOC_CRP_Substrate_DisplayName = Sustrato + #LOC_CRP_Uraninite_DisplayName = Uraninita + #LOC_CRP_Waste_DisplayName = Residuos + #LOC_CRP_WasteWater_DisplayName = Aguas residuales + #LOC_CRP_Water_DisplayName = Agua + //NFT + #LOC_CRP_ArgonGas_DisplayName = Gas argón + #LOC_CRP_ArgonGas_Abbreviation = Ar + #LOC_CRP_Boron_DisplayName = Boro + #LOC_CRP_Boron_Abbreviation = Bo + #LOC_CRP_ResourceLode_DisplayName = Lode de recursos + #LOC_CRP_EnrichedUranium_DisplayName = Uranio enriquecido + #LOC_CRP_EnrichedUranium_Abbreviation = UrEn + #LOC_CRP_DepletedUranium_DisplayName = Uranio empobrecido + #LOC_CRP_DepletedUranium_Abbreviation = UrEm + #LOC_CRP_LqdHydrogen_DisplayName = Hidrógeno líquido + #LOC_CRP_LqdHydrogen_Abbreviation = LH2 + #LOC_CRP_StoredCharge_DisplayName = Carga Almacenada + #LOC_CRP_StoredCharge_Abbreviation = CA + //KSPI-E + #LOC_CRP_Actinides_DisplayName = Actínidos + #LOC_CRP_Actinides_Abbreviation = Act + #LOC_CRP_Aluminium_DisplayName = Aluminio + #LOC_CRP_Aluminium_Abbreviation = Al + #LOC_CRP_Alumina_DisplayName = Alúmina + #LOC_CRP_Alumina_Abbreviation = Aia + #LOC_CRP_Ammonia_DisplayName = Amoníaco + #LOC_CRP_Ammonia_Abbreviation = NH3 + #LOC_CRP_Antimatter_DisplayName = Antimateria + #LOC_CRP_Antimatter_Abbreviation = AM + #LOC_CRP_AntiHydrogen_DisplayName = Anti Hidrógeno + #LOC_CRP_AntiHydrogen_Abbreviation = AH + #LOC_CRP_LqdArgon_DisplayName = ArgónLqd + #LOC_CRP_LqdArgon_Abbreviation = Ar + #LOC_CRP_Borate_DisplayName = Borato + #LOC_CRP_Borate_Abbreviation = Br + #LOC_CRP_Caesium_DisplayName = Cesio + #LOC_CRP_Caesium_Abbreviation = Cs + #LOC_CRP_Calcium_Abbreviation = Ca + #LOC_CRP_Calcium_DisplayName = Calcio + #LOC_CRP_CarbonMonoxide_DisplayName = Monóxido de carbono + #LOC_CRP_CarbonMonoxide_Abbreviation = CO + #LOC_CRP_Carbon_DisplayName = Carbón + #LOC_CRP_Carbon_Abbreviation = C + #LOC_CRP_ChargedParticles_DisplayName = Partículas cargadas + #LOC_CRP_ChargedParticles_Abbreviation = PC + #LOC_CRP_Chlorine_DisplayName = Cloro + #LOC_CRP_Chlorine_Abbreviation = Cl + #LOC_CRP_CompressedAir_DisplayName = Aire comprimido + #LOC_CRP_CompressedAir_Abbreviation = Aire + #LOC_CRP_Decaborane_DisplayName = Decaborano + #LOC_CRP_Decaborane_Abbreviation = DeBo + #LOC_CRP_Deuterium_DisplayName = Deuterio + #LOC_CRP_Deuterium_Abbreviation = D + #LOC_CRP_LqdDeuterium_DisplayName = DeuterioLqd + #LOC_CRP_LqdDeuterium_Abbreviation = D + #LOC_CRP_DepletedFuel_DisplayName = Combustible agotado + #LOC_CRP_DepletedFuel_Abbreviation = Comb Agt + #LOC_CRP_ExoticMatter_DisplayName = Materia exótica + #LOC_CRP_ExoticMatter_Abbreviation = MeX + #LOC_CRP_FusionPellets_DisplayName = Pellets de fusión + #LOC_CRP_FusionPellets_Abbreviation = FP + #LOC_CRP_Fluorine_DisplayName = Flúor + #LOC_CRP_Fluorine_Abbreviation = F + #LOC_CRP_Fluorite_DisplayName = Fluorita + #LOC_CRP_Fluorite_Abbreviation = CaF2 + #LOC_CRP_HeavyWater_DisplayName = Agua pesada + #LOC_CRP_HeavyWater_Abbreviation = D20 + #LOC_CRP_IntakeAtm_DisplayName = AdmisiónAtm + #LOC_CRP_IntakeAtm_Abbreviation = AdAtm + #LOC_CRP_KryptonGas_DisplayName = Gas kriptón + #LOC_CRP_KryptonGas_Abbreviation = Kr + #LOC_CRP_LqdKrypton_DisplayName = KriptónLqd + #LOC_CRP_LqdKrypton_Abbreviation = Kr + #LOC_CRP_NeonGas_DisplayName = Gas neón + #LOC_CRP_NeonGas_Abbreviation = Ne + #LOC_CRP_LqdNeon_DisplayName = NeónLqd + #LOC_CRP_LqdNeon_Abbreviation = Ne + #LOC_CRP_Lithium_DisplayName = Litio + #LOC_CRP_Lithium_Abbreviation = Li7 + #LOC_CRP_Lithium6_DisplayName = Litio6 + #LOC_CRP_Lithium6_Abbreviation = Li6 + #LOC_CRP_LithiumHydride_DisplayName = Hidruro de litio + #LOC_CRP_LithiumHydride_Abbreviation = Li7H + #LOC_CRP_LithiumDeuteride_DisplayName = Deuterio de litio + #LOC_CRP_LithiumDeuteride_Abbreviation = Li6D + #LOC_CRP_LqdAmmonia_DisplayName = AmoníacoLqd + #LOC_CRP_LqdAmmonia_Abbreviation = NH3 + #LOC_CRP_Helium3_DisplayName = Helio3 + #LOC_CRP_Helium3_Abbreviation = He3 + #LOC_CRP_LqdHe3_DisplayName = He3Lqd + #LOC_CRP_LqdHe3_Abbreviation = He3 + #LOC_CRP_Helium4_DisplayName = Helio4 + #LOC_CRP_Helium4_Abbreviation = He4 + #LOC_CRP_LqdHelium_DisplayName = HelioLqd + #LOC_CRP_LqdHelium_Abbreviation = He4 + #LOC_CRP_Nitratine_DisplayName = Nitratina + #LOC_CRP_Nitratine_Abbreviation = Nit + #LOC_CRP_Hexaborane_DisplayName = Hexaborane + #LOC_CRP_Hexaborane_Abbreviation = HxBo + #LOC_CRP_LqdNitrogen_DisplayName = NitrógenoLqd + #LOC_CRP_LqdNitrogen_Abbreviation = N14 + #LOC_CRP_LqdNitrogen15_DisplayName = Nitrógeno15Lqd + #LOC_CRP_LqdNitrogen15_Abbreviation = N15 + #LOC_CRP_Megajoules_DisplayName = Megajulios + #LOC_CRP_Megajoules_Abbreviation = Meg3 + #LOC_CRP_Monazite_DisplayName = Monacita + #LOC_CRP_Monazite_Abbreviation = Monc + #LOC_CRP_LqdOxygen18_DisplayName = Oxígeno18Lqd + #LOC_CRP_LqdOxygen18_Abbreviation = O18 + #LOC_CRP_Salt_DisplayName = Sal + #LOC_CRP_Salt_Abbreviation = Sal + #LOC_CRP_Sodium_DisplayName = Sodio + #LOC_CRP_Sodium_Abbreviation = Na + #LOC_CRP_Sulphur_DisplayName = Azufre + #LOC_CRP_Sulphur_Abbreviation = Az + #LOC_CRP_SolidHydrogen_DisplayName = Hidrógeno sólido + #LOC_CRP_SolidHydrogen_Abbreviation = HS + #LOC_CRP_PolyvinylChloride_DisplayName = Cloruro de polivinilo + #LOC_CRP_PolyvinylChloride_Abbreviation = PVC + #LOC_CRP_Plutonium-238_DisplayName = Plutonio-238 + #LOC_CRP_Plutonium-238_Abbreviation = Pu238 + #LOC_CRP_Regolith_DisplayName = Regolito + #LOC_CRP_Regolith_Abbreviation = R + #LOC_CRP_UF4_DisplayName = UF4 + #LOC_CRP_UF4_Abbreviation = UF4 + #LOC_CRP_Silicates_DisplayName = Silicatos + #LOC_CRP_Silicates_Abbreviation = Sílice + #LOC_CRP_Silicon_DisplayName = Silicio + #LOC_CRP_Silicon_Abbreviation = Si + #LOC_CRP_Spodumene_DisplayName = Espodumena + #LOC_CRP_Spodumene_Abbreviation = LiAl + #LOC_CRP_SolarWind_DisplayName = Viento solar + #LOC_CRP_SolarWind_Abbreviation = VS + #LOC_CRP_ThermalPower_DisplayName = Energía térmica + #LOC_CRP_ThermalPower_Abbreviation = EnTe + #LOC_CRP_Thorium_DisplayName = Torio + #LOC_CRP_Thorium_Abbreviation = To + #LOC_CRP_ThF4_DisplayName = ThF4 + #LOC_CRP_ThF4_Abbreviation = ThF4 + #LOC_CRP_Tritium_DisplayName = Tritio + #LOC_CRP_Tritium_Abbreviation = T + #LOC_CRP_LqdTritium_DisplayName = TritioLqd + #LOC_CRP_LqdTritium_Abbreviation = T + #LOC_CRP_UraniumNitride_DisplayName = Nitruro de uranio + #LOC_CRP_UraniumNitride_Abbreviation = UN + #LOC_CRP_VacuumPlasma_DisplayName = Plasma de vacío + #LOC_CRP_VacuumPlasma_Abbreviation = PV + #LOC_CRP_WasteHeat_DisplayName = Calor residual + #LOC_CRP_WasteHeat_Abbreviation = CR + #LOC_CRP_LqdXenon_DisplayName = XenónLqd + #LOC_CRP_LqdXenon_Abbreviation = Xe + //RealFuels + #LOC_CRP_Aerozine50_DisplayName = Aerozine50 + #LOC_CRP_AK20_DisplayName = AK20 + #LOC_CRP_AK27_DisplayName = AK27 + #LOC_CRP_Aniline_DisplayName = Anilina + #LOC_CRP_AvGas_DisplayName = AvGas + #LOC_CRP_CaveaB_DisplayName = CaveaB + #LOC_CRP_ClF3_DisplayName = ClF3 + #LOC_CRP_ClF5_DisplayName = ClF5 + #LOC_CRP_Diborane_DisplayName = Diborano + #LOC_CRP_Ethane_DisplayName = Etano + #LOC_CRP_Ethanol_DisplayName = Etanol + #LOC_CRP_Ethanol75_DisplayName = Etanol75 + #LOC_CRP_Ethanol90_DisplayName = Etanol90 + #LOC_CRP_Ethylene_DisplayName = Etileno + #LOC_CRP_FLOX30_DisplayName = FLOX30 + #LOC_CRP_FLOX70_DisplayName = FLOX70 + #LOC_CRP_FLOX88_DisplayName = FLOX88 + #LOC_CRP_Furfuryl_DisplayName = Furfurilo + #LOC_CRP_Helium_DisplayName = Helio + #LOC_CRP_HNIW_DisplayName = HNIW + #LOC_CRP_HTP_DisplayName = HTP + #LOC_CRP_HTPB_DisplayName = HTPB + #LOC_CRP_Hydrazine_DisplayName = Hidracina + #LOC_CRP_Hydyne_DisplayName = Hidina + #LOC_CRP_IRFNA-III_DisplayName = IRFNA-III + #LOC_CRP_IRFNA-IV_DisplayName = IRFNA-IV + #LOC_CRP_IWFNA_DisplayName = IWFNA + #LOC_CRP_Kerosene_DisplayName = Queroseno + #LOC_CRP_LeadBallast_DisplayName = Lastre de plomo + #LOC_CRP_LqdFluorine_DisplayName = FlúorLqd + #LOC_CRP_LqdMethane_DisplayName = MetanoLqd + #LOC_CRP_LqdOxygen_DisplayName = OxígenoLqd + #LOC_CRP_Methane_DisplayName = Metano + #LOC_CRP_Methanol_DisplayName = Metanol + #LOC_CRP_MMH_DisplayName = MMH + #LOC_CRP_MON1_DisplayName = MON1 + #LOC_CRP_MON3_DisplayName = MON3 + #LOC_CRP_MON10_DisplayName = MON10 + #LOC_CRP_MON15_DisplayName = MON15 + #LOC_CRP_MON20_DisplayName = MON20 + #LOC_CRP_MON25_DisplayName = MON25 + #LOC_CRP_NGNC_DisplayName = NGNC + #LOC_CRP_N2F4_DisplayName = N2F4 + #LOC_CRP_Nitrogen_DisplayName = Nitrógeno + #LOC_CRP_NitrousOxide_DisplayName = Óxido nitroso + #LOC_CRP_NTO_DisplayName = NTO + #LOC_CRP_OF2_DisplayName = OF2 + #LOC_CRP_PBAN_DisplayName = PBAN + #LOC_CRP_Pentaborane_DisplayName = Pentaborano + #LOC_CRP_PSPC_DisplayName = PSPC + #LOC_CRP_Syntin_DisplayName = Sintina + #LOC_CRP_TEATEB_DisplayName = TEATEB + #LOC_CRP_Tonka250_DisplayName = Tonka250 + #LOC_CRP_Tonka500_DisplayName = Tonka500 + #LOC_CRP_UDMH_DisplayName = UDMH + #LOC_CRP_UH25_DisplayName = UH25 + //DeepFreeze + #LOC_CRP_Glykerol_DisplayName = Glikerol + } +} diff --git a/Distribution/GameData/CommunityResourcePack/Localization/fr-fr.cfg b/Distribution/GameData/CommunityResourcePack/Localization/fr-fr.cfg new file mode 100644 index 0000000..2ae3bc6 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/fr-fr.cfg @@ -0,0 +1,501 @@ +Localization + +{ + + fr-fr + + { + + //USI + + #LOC_CRP_Hydrates_DisplayName = Hydrates + + #LOC_CRP_Gypsum_DisplayName = Gypse + + #LOC_CRP_IntakeLqd_DisplayName = Aduction Liquide + + #LOC_CRP_ColonySupplies_DisplayName = Provisions Coloniales + + #LOC_CRP_Lead_DisplayName = Plomb + + #LOC_CRP_CarbonDioxide_DisplayName = Dioxyde de Carbone + + #LOC_CRP_Chemicals_DisplayName = Produits Chimiques + + #LOC_CRP_Dirt_DisplayName = Boue + + #LOC_CRP_ExoticMinerals_DisplayName = Minerais Exotiques + + #LOC_CRP_Food_DisplayName = Nourriture + + #LOC_CRP_Supplies_DisplayName = Provisions + + #LOC_CRP_Fertilizer_DisplayName = Fertilisant + + #LOC_CRP_Mulch_DisplayName = Compost + + #LOC_CRP_Machinery_DisplayName = Machinerie + + #LOC_CRP_SpecializedParts_DisplayName = Pièces spécialisées + + #LOC_CRP_Recyclables_DisplayName = Recyclables + + #LOC_CRP_Hydrogen_DisplayName = Hydrogène + + #LOC_CRP_Karbonite_DisplayName = Karbonite + + #LOC_CRP_Karborundum_DisplayName = Karborundum + + #LOC_CRP_LqdCO2_DisplayName = CO2 liquide + + #LOC_CRP_LqdCO_DisplayName = CO Liquide + + #LOC_CRP_MaterialKits_DisplayName = Kits de Matériel + + #LOC_CRP_Metals_DisplayName = Métaux + + #LOC_CRP_Minerals_DisplayName = Minéraux + + #LOC_CRP_MetallicOre_DisplayName = Minerai métallique + + #LOC_CRP_Organics_DisplayName = Matières organiques + + #LOC_CRP_Oxygen_DisplayName = Oxygène + + #LOC_CRP_Polymers_DisplayName = Polymères + + #LOC_CRP_RareMetals_DisplayName = Métaux rares + + #LOC_CRP_RefinedExotics_DisplayName = Produits Exotiques Rafinés + + #LOC_CRP_Rock_DisplayName = Roche + + #LOC_CRP_RocketParts_DisplayName = Pièces de Fusées + + #LOC_CRP_SpareParts_DisplayName = Pièces détachées + + #LOC_CRP_Substrate_DisplayName = Substrat + + #LOC_CRP_Uraninite_DisplayName = Uraninite + + #LOC_CRP_Waste_DisplayName = Déchets + + #LOC_CRP_WasteWater_DisplayName = Eaux Usées + + #LOC_CRP_Water_DisplayName = Eau + + //NFT + + #LOC_CRP_ArgonGas_DisplayName = Argon Gazeux + + #LOC_CRP_ArgonGas_Abbreviation = Ar + + #LOC_CRP_Boron_DisplayName = Bore + + #LOC_CRP_Boron_Abbreviation = Bo + + #LOC_CRP_ResourceLode_DisplayName = Gisement exploitable + + #LOC_CRP_EnrichedUranium_DisplayName = Uranium Enrichi + + #LOC_CRP_EnrichedUranium_Abbreviation = UEnr + + #LOC_CRP_DepletedUranium_DisplayName = Uranium Appauvri + + #LOC_CRP_DepletedUranium_Abbreviation = UApp + + #LOC_CRP_LqdHydrogen_DisplayName = Hydrogène Liquide + + #LOC_CRP_LqdHydrogen_Abbreviation = H2Liq + + #LOC_CRP_StoredCharge_DisplayName = Charge Stockée + + #LOC_CRP_StoredCharge_Abbreviation = CS + + //KSPI-E + + #LOC_CRP_Actinides_DisplayName = Actinides + + #LOC_CRP_Actinides_Abbreviation = Act + + #LOC_CRP_Aluminium_DisplayName = Aluminium + + #LOC_CRP_Aluminium_Abbreviation = Al + + #LOC_CRP_Alumina_DisplayName = Alumine + + #LOC_CRP_Alumina_Abbreviation = Alm + + #LOC_CRP_Ammonia_DisplayName = Ammoniaque + + #LOC_CRP_Ammonia_Abbreviation = NH3 + + #LOC_CRP_Antimatter_DisplayName = Antimatière + + #LOC_CRP_Antimatter_Abbreviation = AM + + #LOC_CRP_AntiHydrogen_DisplayName = Antihydrogène + + #LOC_CRP_AntiHydrogen_Abbreviation = AH + + #LOC_CRP_LqdArgon_DisplayName = Argon Liquide + + #LOC_CRP_LqdArgon_Abbreviation = ArLiq + + #LOC_CRP_Borate_DisplayName = Borate + + #LOC_CRP_Borate_Abbreviation = Br + + #LOC_CRP_Caesium_DisplayName = Césium + + #LOC_CRP_Caesium_Abbreviation = Cs + + #LOC_CRP_Calcium_Abbreviation = Ca + + #LOC_CRP_Calcium_DisplayName = Calcium + + #LOC_CRP_CarbonMonoxide_DisplayName = Monoxyde de Carbone + + #LOC_CRP_CarbonMonoxide_Abbreviation = CO + + #LOC_CRP_Carbon_DisplayName = Carbone + + #LOC_CRP_Carbon_Abbreviation = C + + #LOC_CRP_ChargedParticles_DisplayName = Particules Chargées + + #LOC_CRP_ChargedParticles_Abbreviation = PC + + #LOC_CRP_Chlorine_DisplayName = Chlore + + #LOC_CRP_Chlorine_Abbreviation = Cl + + #LOC_CRP_CompressedAir_DisplayName = Air Comprimé + + #LOC_CRP_CompressedAir_Abbreviation = Air + + #LOC_CRP_Decaborane_DisplayName = Décaborane + + #LOC_CRP_Decaborane_Abbreviation = DeBo + + #LOC_CRP_Deuterium_DisplayName = Deutérium + + #LOC_CRP_Deuterium_Abbreviation = D + + #LOC_CRP_LqdDeuterium_DisplayName = Deutérium Liquide + + #LOC_CRP_LqdDeuterium_Abbreviation = D + + #LOC_CRP_DepletedFuel_DisplayName = Combustible Appauvri + + #LOC_CRP_DepletedFuel_Abbreviation = ComApp + + #LOC_CRP_ExoticMatter_DisplayName = Matière Exotique + + #LOC_CRP_ExoticMatter_Abbreviation = MatExo + + #LOC_CRP_FusionPellets_DisplayName = Pastilles de fusion + + #LOC_CRP_FusionPellets_Abbreviation = PF + + #LOC_CRP_Fluorine_DisplayName = Fluor + + #LOC_CRP_Fluorine_Abbreviation = F + + #LOC_CRP_Fluorite_DisplayName = Fluorite + + #LOC_CRP_Fluorite_Abbreviation = CaF2 + + #LOC_CRP_HeavyWater_DisplayName = Eau Lourde + + #LOC_CRP_HeavyWater_Abbreviation = D2O + + #LOC_CRP_IntakeAtm_DisplayName = Entrée d'Air + + #LOC_CRP_IntakeAtm_Abbreviation = EntA + + #LOC_CRP_KryptonGas_DisplayName = Krypton + + #LOC_CRP_KryptonGas_Abbreviation = Kr + + #LOC_CRP_LqdKrypton_DisplayName = Krypton Liquide + + #LOC_CRP_LqdKrypton_Abbreviation = Kr + + #LOC_CRP_NeonGas_DisplayName = Néon + + #LOC_CRP_NeonGas_Abbreviation = Ne + + #LOC_CRP_LqdNeon_DisplayName = Néon Liquide + + #LOC_CRP_LqdNeon_Abbreviation = Ne + + #LOC_CRP_Lithium_DisplayName = Lithium + + #LOC_CRP_Lithium_Abbreviation = Li7 + + #LOC_CRP_Lithium6_DisplayName = Lithium6 + + #LOC_CRP_Lithium6_Abbreviation = Li6 + + #LOC_CRP_LithiumHydride_DisplayName = Hydrure de Lithium + + #LOC_CRP_LithiumHydride_Abbreviation = Li7H + + #LOC_CRP_LithiumDeuteride_DisplayName = Deutérure de Lithium + + #LOC_CRP_LithiumDeuteride_Abbreviation = Li6D + + #LOC_CRP_LqdAmmonia_DisplayName = Ammoniaque Liquide + + #LOC_CRP_LqdAmmonia_Abbreviation = NH3 + + #LOC_CRP_Helium3_DisplayName = Hélium3 + + #LOC_CRP_Helium3_Abbreviation = He3 + + #LOC_CRP_LqdHe3_DisplayName = Hélium3 Liquide + + #LOC_CRP_LqdHe3_Abbreviation = He3 + + #LOC_CRP_Helium4_DisplayName = Hélium4 + + #LOC_CRP_Helium4_Abbreviation = He4 + + #LOC_CRP_LqdHelium_DisplayName = Hélium Liquide + + #LOC_CRP_LqdHelium_Abbreviation = He4 + + #LOC_CRP_Nitratine_DisplayName = Nitratine + + #LOC_CRP_Nitratine_Abbreviation = Nit + + #LOC_CRP_Hexaborane_DisplayName = Héxaborane + + #LOC_CRP_Hexaborane_Abbreviation = HxBo + + #LOC_CRP_LqdNitrogen_DisplayName = Nitrogène Liquide + + #LOC_CRP_LqdNitrogen_Abbreviation = N14 + + #LOC_CRP_LqdNitrogen15_DisplayName = Nitrogène15 Liquide + + #LOC_CRP_LqdNitrogen15_Abbreviation = N15 + + #LOC_CRP_Megajoules_DisplayName = Mégajoules + + #LOC_CRP_Megajoules_Abbreviation = Meg3 + + #LOC_CRP_Monazite_DisplayName = Monazite + + #LOC_CRP_Monazite_Abbreviation = Monz + + #LOC_CRP_LqdOxygen18_DisplayName = Oxygène18 Liquide + + #LOC_CRP_LqdOxygen18_Abbreviation = O18 + + #LOC_CRP_Salt_DisplayName = Sel + + #LOC_CRP_Salt_Abbreviation = Sel + + #LOC_CRP_Sodium_DisplayName = Sodium + + #LOC_CRP_Sodium_Abbreviation = Na + + #LOC_CRP_Sulphur_DisplayName = Souffre + + #LOC_CRP_Sulphur_Abbreviation = S + + #LOC_CRP_SolidHydrogen_DisplayName = Hydrogène Solide + + #LOC_CRP_SolidHydrogen_Abbreviation = HS + + #LOC_CRP_PolyvinylChloride_DisplayName = Polychlorure de Vinyle + + #LOC_CRP_PolyvinylChloride_Abbreviation = PVC + + #LOC_CRP_Plutonium-238_DisplayName = Plutonium-238 + + #LOC_CRP_Plutonium-238_Abbreviation = Pu238 + + #LOC_CRP_Regolith_DisplayName = Régolithe + + #LOC_CRP_Regolith_Abbreviation = R + + #LOC_CRP_UF4_DisplayName = Fluorure d'Uranium4 + + #LOC_CRP_UF4_Abbreviation = UF4 + + #LOC_CRP_Silicates_DisplayName = Silicates + + #LOC_CRP_Silicates_Abbreviation = Silica + + #LOC_CRP_Silicon_DisplayName = Silicone + + #LOC_CRP_Silicon_Abbreviation = Si + + #LOC_CRP_Spodumene_DisplayName = Spodumène + + #LOC_CRP_Spodumene_Abbreviation = LiAl + + #LOC_CRP_SolarWind_DisplayName = Vents Solaire + + #LOC_CRP_SolarWind_Abbreviation = VS + + #LOC_CRP_ThermalPower_DisplayName = Energie Thermique + + #LOC_CRP_ThermalPower_Abbreviation = ET + + #LOC_CRP_Thorium_DisplayName = Thorium + + #LOC_CRP_Thorium_Abbreviation = Th + + #LOC_CRP_ThF4_DisplayName = Fluorure de thorium + + #LOC_CRP_ThF4_Abbreviation = ThF4 + + #LOC_CRP_Tritium_DisplayName = Tritium + + #LOC_CRP_Tritium_Abbreviation = T + + #LOC_CRP_LqdTritium_DisplayName = Tritium Liquide + + #LOC_CRP_LqdTritium_Abbreviation = T + + #LOC_CRP_UraniumNitride_DisplayName = Nitrure d'Uranium + + #LOC_CRP_UraniumNitride_Abbreviation = NU + + #LOC_CRP_VacuumPlasma_DisplayName = Projection Plasmique + + #LOC_CRP_VacuumPlasma_Abbreviation = PP + + #LOC_CRP_WasteHeat_DisplayName = Chaleur résiduelle + + #LOC_CRP_WasteHeat_Abbreviation = DT + + #LOC_CRP_LqdXenon_DisplayName = Xénon Liquide + + #LOC_CRP_LqdXenon_Abbreviation = Xe + + //RealFuels + + #LOC_CRP_Aerozine50_DisplayName = Aérozine50 + + #LOC_CRP_AK20_DisplayName = AK20 + + #LOC_CRP_AK27_DisplayName = AK27 + + #LOC_CRP_Aniline_DisplayName = Aniline + + #LOC_CRP_AvGas_DisplayName = AvGas + + #LOC_CRP_CaveaB_DisplayName = CaveaB + + #LOC_CRP_ClF3_DisplayName = ClF3 + + #LOC_CRP_ClF5_DisplayName = ClF5 + + #LOC_CRP_Diborane_DisplayName = Diborane + + #LOC_CRP_Ethane_DisplayName = Ethane + + #LOC_CRP_Ethanol_DisplayName = Ethanol + + #LOC_CRP_Ethanol75_DisplayName = Ethanol75 + + #LOC_CRP_Ethanol90_DisplayName = Ethanol90 + + #LOC_CRP_Ethylene_DisplayName = Ethylène + + #LOC_CRP_FLOX30_DisplayName = FLOX30 + + #LOC_CRP_FLOX70_DisplayName = FLOX70 + + #LOC_CRP_FLOX88_DisplayName = FLOX88 + + #LOC_CRP_Furfuryl_DisplayName = Alcool furfurylique + + #LOC_CRP_Helium_DisplayName = Hélium + + #LOC_CRP_HNIW_DisplayName = HNIW + + #LOC_CRP_HTP_DisplayName = HTP + + #LOC_CRP_HTPB_DisplayName = HTPB + + #LOC_CRP_Hydrazine_DisplayName = Hydrazine + + #LOC_CRP_Hydyne_DisplayName = Hydyne + + #LOC_CRP_IRFNA-III_DisplayName = IRFNA-III + + #LOC_CRP_IRFNA-IV_DisplayName = IRFNA-IV + + #LOC_CRP_IWFNA_DisplayName = IWFNA + + #LOC_CRP_Kerosene_DisplayName = Kérosene + + #LOC_CRP_LeadBallast_DisplayName = Lest + + #LOC_CRP_LqdFluorine_DisplayName = Fluor liquide + + #LOC_CRP_LqdMethane_DisplayName = Méthane Liquide + + #LOC_CRP_LqdOxygen_DisplayName = Oxygène Liquide + + #LOC_CRP_Methane_DisplayName = Méthane + + #LOC_CRP_Methanol_DisplayName = Méthanol + + #LOC_CRP_MMH_DisplayName = MMH + + #LOC_CRP_MON1_DisplayName = MON1 + + #LOC_CRP_MON3_DisplayName = MON3 + + #LOC_CRP_MON10_DisplayName = MON10 + + #LOC_CRP_MON15_DisplayName = MON15 + + #LOC_CRP_MON20_DisplayName = MON20 + + #LOC_CRP_MON25_DisplayName = MON25 + + #LOC_CRP_NGNC_DisplayName = NGNC + + #LOC_CRP_N2F4_DisplayName = N2F4 + + #LOC_CRP_Nitrogen_DisplayName = Nitrogène + + #LOC_CRP_NitrousOxide_DisplayName = Protoxyde d'Azote + + #LOC_CRP_NTO_DisplayName = NOS + + #LOC_CRP_OF2_DisplayName = OF2 + + #LOC_CRP_PBAN_DisplayName = PBAN + + #LOC_CRP_Pentaborane_DisplayName = Pentaborane + + #LOC_CRP_PSPC_DisplayName = PSPC + + #LOC_CRP_Syntin_DisplayName = Syntin + + #LOC_CRP_TEATEB_DisplayName = TEATEB + + #LOC_CRP_Tonka250_DisplayName = Tonka250 + + #LOC_CRP_Tonka500_DisplayName = Tonka500 + + #LOC_CRP_UDMH_DisplayName = UDMH + + #LOC_CRP_UH25_DisplayName = UH25 + + //DeepFreeze + + #LOC_CRP_Glykerol_DisplayName = Glycérol + + } + +} diff --git a/Distribution/GameData/CommunityResourcePack/Localization/ja.cfg b/Distribution/GameData/CommunityResourcePack/Localization/ja.cfg new file mode 100644 index 0000000..7d341a4 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/ja.cfg @@ -0,0 +1,234 @@ +Localization +{ + ja + { + //USI + #LOC_CRP_Hydrates_DisplayName = Hydrates + #LOC_CRP_Gypsum_DisplayName = Gypsum + #LOC_CRP_IntakeLqd_DisplayName = IntakeLqd + #LOC_CRP_ColonySupplies_DisplayName = ColonySupplies + #LOC_CRP_Lead_DisplayName = Lead + #LOC_CRP_CarbonDioxide_DisplayName = CarbonDioxide + #LOC_CRP_Chemicals_DisplayName = Chemicals + #LOC_CRP_Dirt_DisplayName = Dirt + #LOC_CRP_ExoticMinerals_DisplayName = ExoticMinerals + #LOC_CRP_Food_DisplayName = Food + #LOC_CRP_Supplies_DisplayName = Supplies + #LOC_CRP_Fertilizer_DisplayName = Fertilizer + #LOC_CRP_Mulch_DisplayName = Mulch + #LOC_CRP_Machinery_DisplayName = Machinery + #LOC_CRP_SpecializedParts_DisplayName = SpecializedParts + #LOC_CRP_Recyclables_DisplayName = Recyclables + #LOC_CRP_Hydrogen_DisplayName = Hydrogen + #LOC_CRP_Karbonite_DisplayName = Karbonite + #LOC_CRP_Karborundum_DisplayName = Karborundum + #LOC_CRP_LqdCO2_DisplayName = LqdCO2 + #LOC_CRP_LqdCO_DisplayName = LqdCO + #LOC_CRP_MaterialKits_DisplayName = MaterialKits + #LOC_CRP_Metals_DisplayName = Metals + #LOC_CRP_Minerals_DisplayName = Minerals + #LOC_CRP_MetallicOre_DisplayName = MetallicOre + #LOC_CRP_Organics_DisplayName = Organics + #LOC_CRP_Oxygen_DisplayName = Oxygen + #LOC_CRP_Polymers_DisplayName = Polymers + #LOC_CRP_RareMetals_DisplayName = RareMetals + #LOC_CRP_RefinedExotics_DisplayName = RefinedExotics + #LOC_CRP_Rock_DisplayName = Rock + #LOC_CRP_RocketParts_DisplayName = RocketParts + #LOC_CRP_SpareParts_DisplayName = SpareParts + #LOC_CRP_Substrate_DisplayName = Substrate + #LOC_CRP_Uraninite_DisplayName = Uraninite + #LOC_CRP_Waste_DisplayName = Waste + #LOC_CRP_WasteWater_DisplayName = WasteWater + #LOC_CRP_Water_DisplayName = Water + //NFT + #LOC_CRP_ArgonGas_DisplayName = Argon Gas + #LOC_CRP_ArgonGas_Abbreviation = Ar + #LOC_CRP_Boron_DisplayName = Boron + #LOC_CRP_Boron_Abbreviation = Bo + #LOC_CRP_ResourceLode_DisplayName = ResourceLode + #LOC_CRP_EnrichedUranium_DisplayName = Enriched Uranium + #LOC_CRP_EnrichedUranium_Abbreviation = EnrU + #LOC_CRP_DepletedUranium_DisplayName = Depleted Uranium + #LOC_CRP_DepletedUranium_Abbreviation = DepU + #LOC_CRP_LqdHydrogen_DisplayName = Liquid Hydrogen + #LOC_CRP_LqdHydrogen_Abbreviation = LH2 + #LOC_CRP_StoredCharge_DisplayName = Stored Charge + #LOC_CRP_StoredCharge_Abbreviation = SC + //KSPI-E + #LOC_CRP_Actinides_DisplayName = Actinides + #LOC_CRP_Actinides_Abbreviation = Act + #LOC_CRP_Aluminium_DisplayName = Aluminium + #LOC_CRP_Aluminium_Abbreviation = Al + #LOC_CRP_Alumina_DisplayName = Alumina + #LOC_CRP_Alumina_Abbreviation = Aia + #LOC_CRP_Ammonia_DisplayName = Ammonia + #LOC_CRP_Ammonia_Abbreviation = NH3 + #LOC_CRP_Antimatter_DisplayName = Antimatter + #LOC_CRP_Antimatter_Abbreviation = AM + #LOC_CRP_LqdArgon_DisplayName = LqdArgon + #LOC_CRP_LqdArgon_Abbreviation = Ar + #LOC_CRP_Borate_DisplayName = Borate + #LOC_CRP_Borate_Abbreviation = Br + #LOC_CRP_Caesium_DisplayName = Caesium + #LOC_CRP_Caesium_Abbreviation = Cs + #LOC_CRP_CarbonMonoxide_DisplayName = CarbonMonoxide + #LOC_CRP_CarbonMonoxide_Abbreviation = CO + #LOC_CRP_Carbon_DisplayName = Carbon + #LOC_CRP_Carbon_Abbreviation = C + #LOC_CRP_ChargedParticles_DisplayName = ChargedParticles + #LOC_CRP_ChargedParticles_Abbreviation = CP + #LOC_CRP_Decaborane_DisplayName = Decaborane + #LOC_CRP_Decaborane_Abbreviation = DeBo + #LOC_CRP_Deuterium_DisplayName = Deuterium + #LOC_CRP_Deuterium_Abbreviation = D + #LOC_CRP_LqdDeuterium_DisplayName = LqdDeuterium + #LOC_CRP_LqdDeuterium_Abbreviation = D + #LOC_CRP_DepletedFuel_DisplayName = DepletedFuel + #LOC_CRP_DepletedFuel_Abbreviation = DepF + #LOC_CRP_ExoticMatter_DisplayName = ExoticMatter + #LOC_CRP_ExoticMatter_Abbreviation = EcM + #LOC_CRP_FusionPellets_DisplayName = FusionPellets + #LOC_CRP_Fluorine_DisplayName = Fluorine + #LOC_CRP_Fluorine_Abbreviation = F + #LOC_CRP_HeavyWater_DisplayName = HeavyWater + #LOC_CRP_HeavyWater_Abbreviation = D20 + #LOC_CRP_IntakeAtm_DisplayName = IntakeAtm + #LOC_CRP_IntakeAtm_Abbreviation = IntA + #LOC_CRP_KryptonGas_DisplayName = KryptonGas + #LOC_CRP_KryptonGas_Abbreviation = Kr + #LOC_CRP_LqdKrypton_DisplayName = LqdKrypton + #LOC_CRP_LqdKrypton_Abbreviation = Kr + #LOC_CRP_NeonGas_DisplayName = NeonGas + #LOC_CRP_NeonGas_Abbreviation = Ne + #LOC_CRP_LqdNeon_DisplayName = LqdNeon + #LOC_CRP_LqdNeon_Abbreviation = Ne + #LOC_CRP_Lithium_DisplayName = Lithium + #LOC_CRP_Lithium_Abbreviation = Li7 + #LOC_CRP_Lithium6_DisplayName = Lithium6 + #LOC_CRP_Lithium6_Abbreviation = Li6 + #LOC_CRP_LithiumHydride_DisplayName = LithiumHydride + #LOC_CRP_LithiumHydride_Abbreviation = Li7H + #LOC_CRP_LithiumHydride_Title = LithiumHydride + #LOC_CRP_LithiumDeuteride_DisplayName = LithiumDeuteride + #LOC_CRP_LithiumDeuteride_Abbreviation = Li6D + #LOC_CRP_LithiumDeuteride_Title = LithiumDeuteride + #LOC_CRP_LqdAmmonia_DisplayName = LqdAmmonia + #LOC_CRP_LqdAmmonia_Abbreviation = NH3 + #LOC_CRP_Helium3_DisplayName = Helium3 + #LOC_CRP_Helium3_Abbreviation = He3 + #LOC_CRP_LqdHe3_DisplayName = LqdHe3 + #LOC_CRP_LqdHe3_Abbreviation = He3 + #LOC_CRP_Helium4_DisplayName = Helium4 + #LOC_CRP_Helium4_Abbreviation = He4 + #LOC_CRP_LqdHelium_DisplayName = LqdHelium + #LOC_CRP_LqdHelium_Abbreviation = He4 + #LOC_CRP_Nitratine_DisplayName = Nitratine + #LOC_CRP_Nitratine_Title = Nitratine + #LOC_CRP_Hexaborane_DisplayName = Hexaborane + #LOC_CRP_LqdNitrogen_DisplayName = LqdNitrogen + #LOC_CRP_LqdNitrogen_Abbreviation = N14 + #LOC_CRP_LqdNitrogen15_DisplayName = LqdNitrogen15 + #LOC_CRP_LqdNitrogen15_Abbreviation = N15 + #LOC_CRP_Megajoules_DisplayName = Megajoules + #LOC_CRP_Megajoules_Abbreviation = Meg3 + #LOC_CRP_Monazite_DisplayName = Monazite + #LOC_CRP_Monazite_Abbreviation = Monz + #LOC_CRP_LqdOxygen18_DisplayName = LqdOxygen18 + #LOC_CRP_LqdOxygen18_Abbreviation = O18 + #LOC_CRP_Sodium_DisplayName = Sodium + #LOC_CRP_Sodium_Abbreviation = Na + #LOC_CRP_PolyvinylChloride_DisplayName = PolyvinylChloride + #LOC_CRP_PolyvinylChloride_Abbreviation = PVC + #LOC_CRP_Plutonium-238_DisplayName = Plutonium-238 + #LOC_CRP_Plutonium-238_Abbreviation = Pu238 + #LOC_CRP_Regolith_DisplayName = Regolith + #LOC_CRP_Regolith_Abbreviation = R + #LOC_CRP_UF4_DisplayName = UF4 + #LOC_CRP_UF4_Abbreviation = UF4 + #LOC_CRP_Silicates_DisplayName = Silicates + #LOC_CRP_Silicates_Abbreviation = Silica + #LOC_CRP_Silicon_DisplayName = Silicon + #LOC_CRP_Silicon_Abbreviation = Si + #LOC_CRP_SolarWind_DisplayName = SolarWind + #LOC_CRP_SolarWind_Abbreviation = SW + #LOC_CRP_ThermalPower_DisplayName = ThermalPower + #LOC_CRP_ThermalPower_Abbreviation = ThP + #LOC_CRP_Thorium_DisplayName = Thorium + #LOC_CRP_ThF4_DisplayName = ThF4 + #LOC_CRP_ThF4_Abbreviation = ThF4 + #LOC_CRP_Tritium_DisplayName = Tritium + #LOC_CRP_Tritium_Abbreviation = T + #LOC_CRP_Tritium_Title = Tritium Gas + #LOC_CRP_LqdTritium_DisplayName = LqdTritium + #LOC_CRP_LqdTritium_Abbreviation = T + #LOC_CRP_UraniumNitride_DisplayName = UraniumNitride + #LOC_CRP_UraniumNitride_Abbreviation = UN + #LOC_CRP_VacuumPlasma_DisplayName = VacuumPlasma + #LOC_CRP_VacuumPlasma_Abbreviation = VP + #LOC_CRP_WasteHeat_DisplayName = WasteHeat + #LOC_CRP_WasteHeat_Abbreviation = WH + #LOC_CRP_LqdXenon_DisplayName = LqdXenon + #LOC_CRP_LqdXenon_Abbreviation = Xe + #LOC_CRP_LqdXenon_Title = Liquid Xenon + //RealFuels + #LOC_CRP_Aerozine50_DisplayName = Aerozine50 + #LOC_CRP_AK20_DisplayName = AK20 + #LOC_CRP_AK27_DisplayName = AK27 + #LOC_CRP_Aniline_DisplayName = Aniline + #LOC_CRP_AvGas_DisplayName = AvGas + #LOC_CRP_CaveaB_DisplayName = CaveaB + #LOC_CRP_ClF3_DisplayName = ClF3 + #LOC_CRP_ClF5_DisplayName = ClF5 + #LOC_CRP_Diborane_DisplayName = Diborane + #LOC_CRP_Ethane_DisplayName = Ethane + #LOC_CRP_Ethanol_DisplayName = Ethanol + #LOC_CRP_Ethanol75_DisplayName = Ethanol75 + #LOC_CRP_Ethanol90_DisplayName = Ethanol90 + #LOC_CRP_Ethylene_DisplayName = Ethylene + #LOC_CRP_FLOX30_DisplayName = FLOX30 + #LOC_CRP_FLOX70_DisplayName = FLOX70 + #LOC_CRP_FLOX88_DisplayName = FLOX88 + #LOC_CRP_Furfuryl_DisplayName = Furfuryl + #LOC_CRP_Helium_DisplayName = Helium + #LOC_CRP_HNIW_DisplayName = HNIW + #LOC_CRP_HTP_DisplayName = HTP + #LOC_CRP_HTPB_DisplayName = HTPB + #LOC_CRP_Hydrazine_DisplayName = Hydrazine + #LOC_CRP_Hydyne_DisplayName = Hydyne + #LOC_CRP_IRFNA-III_DisplayName = IRFNA-III + #LOC_CRP_IRFNA-IV_DisplayName = IRFNA-IV + #LOC_CRP_IWFNA_DisplayName = IWFNA + #LOC_CRP_Kerosene_DisplayName = Kerosene + #LOC_CRP_LeadBallast_DisplayName = LeadBallast + #LOC_CRP_LqdFluorine_DisplayName = LqdFluorine + #LOC_CRP_LqdMethane_DisplayName = LqdMethane + #LOC_CRP_LqdOxygen_DisplayName = LqdOxygen + #LOC_CRP_Methane_DisplayName = Methane + #LOC_CRP_Methanol_DisplayName = Methanol + #LOC_CRP_MMH_DisplayName = MMH + #LOC_CRP_MON1_DisplayName = MON1 + #LOC_CRP_MON3_DisplayName = MON3 + #LOC_CRP_MON10_DisplayName = MON10 + #LOC_CRP_MON15_DisplayName = MON15 + #LOC_CRP_MON20_DisplayName = MON20 + #LOC_CRP_MON25_DisplayName = MON25 + #LOC_CRP_NGNC_DisplayName = NGNC + #LOC_CRP_N2F4_DisplayName = N2F4 + #LOC_CRP_Nitrogen_DisplayName = Nitrogen + #LOC_CRP_NitrousOxide_DisplayName = NitrousOxide + #LOC_CRP_NTO_DisplayName = NTO + #LOC_CRP_OF2_DisplayName = OF2 + #LOC_CRP_PBAN_DisplayName = PBAN + #LOC_CRP_Pentaborane_DisplayName = Pentaborane + #LOC_CRP_PSPC_DisplayName = PSPC + #LOC_CRP_Syntin_DisplayName = Syntin + #LOC_CRP_TEATEB_DisplayName = TEATEB + #LOC_CRP_Tonka250_DisplayName = Tonka250 + #LOC_CRP_Tonka500_DisplayName = Tonka500 + #LOC_CRP_UDMH_DisplayName = UDMH + #LOC_CRP_UH25_DisplayName = UH25 + //DeepFreeze + #LOC_CRP_Glykerol_DisplayName = Glykerol + } +} diff --git a/Distribution/GameData/CommunityResourcePack/Localization/pt-br.cfg b/Distribution/GameData/CommunityResourcePack/Localization/pt-br.cfg new file mode 100644 index 0000000..91f6ebb --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/pt-br.cfg @@ -0,0 +1,251 @@ +Localization +{ + pt-br + { + //USI + #LOC_CRP_Hydrates_DisplayName = Hidratos + #LOC_CRP_Gypsum_DisplayName = Gesso + #LOC_CRP_IntakeLqd_DisplayName = EntradaLqd + #LOC_CRP_ColonySupplies_DisplayName = Suprimentos de Colônia + #LOC_CRP_Lead_DisplayName = Chumbo + #LOC_CRP_CarbonDioxide_DisplayName = Dióxido de Carbono + #LOC_CRP_Chemicals_DisplayName = Produtos Químicos + #LOC_CRP_Dirt_DisplayName = Sujeira + #LOC_CRP_ExoticMinerals_DisplayName = Minerais Exóticos + #LOC_CRP_Food_DisplayName = Comida + #LOC_CRP_Supplies_DisplayName = Suprimentos + #LOC_CRP_Fertilizer_DisplayName = Fertilizante + #LOC_CRP_Mulch_DisplayName = Adubo + #LOC_CRP_Machinery_DisplayName = Maquinário + #LOC_CRP_SpecializedParts_DisplayName = Peças Especializadas + #LOC_CRP_Recyclables_DisplayName = Recicláveis + #LOC_CRP_Hydrogen_DisplayName = Hidrogênio + #LOC_CRP_Karbonite_DisplayName = Karbonite + #LOC_CRP_Karborundum_DisplayName = Carbeto de Silício + #LOC_CRP_LqdCO2_DisplayName = CO2Lqd + #LOC_CRP_LqdCO_DisplayName = COLqd + #LOC_CRP_MaterialKits_DisplayName = Kits de Materiais + #LOC_CRP_Metals_DisplayName = Metais + #LOC_CRP_Minerals_DisplayName = Minerais + #LOC_CRP_MetallicOre_DisplayName = Minério Metálico + #LOC_CRP_Organics_DisplayName = Orgânico + #LOC_CRP_Oxygen_DisplayName = Oxigênio + #LOC_CRP_Polymers_DisplayName = Polímeros + #LOC_CRP_RareMetals_DisplayName = Metais Raros + #LOC_CRP_RefinedExotics_DisplayName = Exóticos Refinados + #LOC_CRP_Rock_DisplayName = Rocha + #LOC_CRP_RocketParts_DisplayName = Peças de Foguete + #LOC_CRP_SpareParts_DisplayName = Peças de Reposição + #LOC_CRP_Substrate_DisplayName = Substrato + #LOC_CRP_Uraninite_DisplayName = Uraninita + #LOC_CRP_Waste_DisplayName = Resíduos + #LOC_CRP_WasteWater_DisplayName = Águas Residuais + #LOC_CRP_Water_DisplayName = Água + //NFT + #LOC_CRP_ArgonGas_DisplayName = Gás Argônio + #LOC_CRP_ArgonGas_Abbreviation = Ar + #LOC_CRP_Boron_DisplayName = Boro + #LOC_CRP_Boron_Abbreviation = Bo + #LOC_CRP_ResourceLode_DisplayName = Veio de Minério + #LOC_CRP_EnrichedUranium_DisplayName = Urânio Enriquecido + #LOC_CRP_EnrichedUranium_Abbreviation = EnrU + #LOC_CRP_DepletedUranium_DisplayName = Urânio Empobrecido + #LOC_CRP_DepletedUranium_Abbreviation = EmpU + #LOC_CRP_LqdHydrogen_DisplayName = Hidrogênio Líquido + #LOC_CRP_LqdHydrogen_Abbreviation = LH2 + #LOC_CRP_StoredCharge_DisplayName = Carga Armazenada + #LOC_CRP_StoredCharge_Abbreviation = CA + //KSPI-E + #LOC_CRP_Actinides_DisplayName = Actinídeos + #LOC_CRP_Actinides_Abbreviation = Act + #LOC_CRP_Aluminium_DisplayName = Alumínio + #LOC_CRP_Aluminium_Abbreviation = Al + #LOC_CRP_Alumina_DisplayName = Alumina + #LOC_CRP_Alumina_Abbreviation = Aia + #LOC_CRP_Ammonia_DisplayName = Amônia + #LOC_CRP_Ammonia_Abbreviation = NH3 + #LOC_CRP_Antimatter_DisplayName = Antimatéria + #LOC_CRP_Antimatter_Abbreviation = AM + #LOC_CRP_AntiHydrogen_DisplayName = Anti-Hidrogênio + #LOC_CRP_AntiHydrogen_Abbreviation = AH + #LOC_CRP_LqdArgon_DisplayName = ArgônioLqd + #LOC_CRP_LqdArgon_Abbreviation = Ar + #LOC_CRP_Borate_DisplayName = Borato + #LOC_CRP_Borate_Abbreviation = Br + #LOC_CRP_Caesium_DisplayName = Césio + #LOC_CRP_Caesium_Abbreviation = Cs + #LOC_CRP_Calcium_Abbreviation = Ca + #LOC_CRP_Calcium_DisplayName = Cálcio + #LOC_CRP_CarbonMonoxide_DisplayName = Monóxido de Carbono + #LOC_CRP_CarbonMonoxide_Abbreviation = CO + #LOC_CRP_Carbon_DisplayName = Carbono + #LOC_CRP_Carbon_Abbreviation = C + #LOC_CRP_ChargedParticles_DisplayName = Partículas Carregadas + #LOC_CRP_ChargedParticles_Abbreviation = CP + #LOC_CRP_Chlorine_DisplayName = Cloro + #LOC_CRP_Chlorine_Abbreviation = Cl + #LOC_CRP_CompressedAir_DisplayName = Ar Comprimido + #LOC_CRP_CompressedAir_Abbreviation = ArC + #LOC_CRP_Decaborane_DisplayName = Decaborane + #LOC_CRP_Decaborane_Abbreviation = DeBo + #LOC_CRP_Deuterium_DisplayName = Deutério + #LOC_CRP_Deuterium_Abbreviation = D + #LOC_CRP_LqdDeuterium_DisplayName = DeutérioLqd + #LOC_CRP_LqdDeuterium_Abbreviation = D + #LOC_CRP_DepletedFuel_DisplayName = Combustível Esgotado + #LOC_CRP_DepletedFuel_Abbreviation = CombEg + #LOC_CRP_ExoticMatter_DisplayName = Matéria Exótica + #LOC_CRP_ExoticMatter_Abbreviation = MEx + #LOC_CRP_FusionPellets_DisplayName = Pelotas de Fusão + #LOC_CRP_FusionPellets_Abbreviation = PF + #LOC_CRP_Fluorine_DisplayName = Flúor + #LOC_CRP_Fluorine_Abbreviation = F + #LOC_CRP_Fluorite_DisplayName = Fluorita + #LOC_CRP_Fluorite_Abbreviation = CaF2 + #LOC_CRP_HeavyWater_DisplayName = Água Pesada + #LOC_CRP_HeavyWater_Abbreviation = D20 + #LOC_CRP_IntakeAtm_DisplayName = EntradaAtm + #LOC_CRP_IntakeAtm_Abbreviation = EntA + #LOC_CRP_KryptonGas_DisplayName = Gás de Criptônio + #LOC_CRP_KryptonGas_Abbreviation = Kr + #LOC_CRP_LqdKrypton_DisplayName = CriptônioLqd + #LOC_CRP_LqdKrypton_Abbreviation = Kr + #LOC_CRP_NeonGas_DisplayName = Gás Neon + #LOC_CRP_NeonGas_Abbreviation = Ne + #LOC_CRP_LqdNeon_DisplayName = NeonLqd + #LOC_CRP_LqdNeon_Abbreviation = Ne + #LOC_CRP_Lithium_DisplayName = Lítio + #LOC_CRP_Lithium_Abbreviation = Li7 + #LOC_CRP_Lithium6_DisplayName = Lítio6 + #LOC_CRP_Lithium6_Abbreviation = Li6 + #LOC_CRP_LithiumHydride_DisplayName = Hidreto De Lítio + #LOC_CRP_LithiumHydride_Abbreviation = Li7H + #LOC_CRP_LithiumDeuteride_DisplayName = Deuteride do Lítio + #LOC_CRP_LithiumDeuteride_Abbreviation = Li6D + #LOC_CRP_LqdAmmonia_DisplayName = AmôniaLqd + #LOC_CRP_LqdAmmonia_Abbreviation = NH3 + #LOC_CRP_Helium3_DisplayName = Hélio3 + #LOC_CRP_Helium3_Abbreviation = He3 + #LOC_CRP_LqdHe3_DisplayName = LqdHe3 + #LOC_CRP_LqdHe3_Abbreviation = He3 + #LOC_CRP_Helium4_DisplayName = Hélio4 + #LOC_CRP_Helium4_Abbreviation = He4 + #LOC_CRP_LqdHelium_DisplayName = HélioLqd + #LOC_CRP_LqdHelium_Abbreviation = He4 + #LOC_CRP_Nitratine_DisplayName = Nitratina + #LOC_CRP_Nitratine_Abbreviation = Nit + #LOC_CRP_Hexaborane_DisplayName = Hexaborane + #LOC_CRP_Hexaborane_Abbreviation = HxBo + #LOC_CRP_LqdNitrogen_DisplayName = NitrogênioLqd + #LOC_CRP_LqdNitrogen_Abbreviation = N14 + #LOC_CRP_LqdNitrogen15_DisplayName = Nitrogênio15Lqd + #LOC_CRP_LqdNitrogen15_Abbreviation = N15 + #LOC_CRP_Megajoules_DisplayName = Megajoules + #LOC_CRP_Megajoules_Abbreviation = Meg3 + #LOC_CRP_Monazite_DisplayName = Monazita + #LOC_CRP_Monazite_Abbreviation = Monz + #LOC_CRP_LqdOxygen18_DisplayName = Oxigênio18Lqd + #LOC_CRP_LqdOxygen18_Abbreviation = O18 + #LOC_CRP_Salt_DisplayName = Sal + #LOC_CRP_Salt_Abbreviation = Sal + #LOC_CRP_Sodium_DisplayName = Sódio + #LOC_CRP_Sodium_Abbreviation = Na + #LOC_CRP_Sulphur_DisplayName = Enxofre + #LOC_CRP_Sulphur_Abbreviation = S + #LOC_CRP_SolidHydrogen_DisplayName = Hidrogênio Sólido + #LOC_CRP_SolidHydrogen_Abbreviation = HS + #LOC_CRP_PolyvinylChloride_DisplayName = Cloreto De Polivinila + #LOC_CRP_PolyvinylChloride_Abbreviation = PVC + #LOC_CRP_Plutonium-238_DisplayName = Plutônio-238 + #LOC_CRP_Plutonium-238_Abbreviation = Pu238 + #LOC_CRP_Regolith_DisplayName = Regolito + #LOC_CRP_Regolith_Abbreviation = R + #LOC_CRP_UF4_DisplayName = UF4 + #LOC_CRP_UF4_Abbreviation = UF4 + #LOC_CRP_Silicates_DisplayName = Silicatos + #LOC_CRP_Silicates_Abbreviation = Sílica + #LOC_CRP_Silicon_DisplayName = Silício + #LOC_CRP_Silicon_Abbreviation = Si + #LOC_CRP_Spodumene_DisplayName = Spodumene + #LOC_CRP_Spodumene_Abbreviation = LiAl + #LOC_CRP_SolarWind_DisplayName = Vento Solar + #LOC_CRP_SolarWind_Abbreviation = VS + #LOC_CRP_ThermalPower_DisplayName = Poder Térmico + #LOC_CRP_ThermalPower_Abbreviation = ThP + #LOC_CRP_Thorium_DisplayName = Tório + #LOC_CRP_Thorium_Abbreviation = Th + #LOC_CRP_ThF4_DisplayName = ThF4 + #LOC_CRP_ThF4_Abbreviation = ThF4 + #LOC_CRP_Tritium_DisplayName = Trítio + #LOC_CRP_Tritium_Abbreviation = T + #LOC_CRP_LqdTritium_DisplayName = TrítioLqd + #LOC_CRP_LqdTritium_Abbreviation = T + #LOC_CRP_UraniumNitride_DisplayName = Nitreto de Urânio + #LOC_CRP_UraniumNitride_Abbreviation = UN + #LOC_CRP_VacuumPlasma_DisplayName = Plasma a Vácuo + #LOC_CRP_VacuumPlasma_Abbreviation = VP + #LOC_CRP_WasteHeat_DisplayName = Calor Residual + #LOC_CRP_WasteHeat_Abbreviation = CR + #LOC_CRP_LqdXenon_DisplayName = XenônioLqd + #LOC_CRP_LqdXenon_Abbreviation = Xe + //RealFuels + #LOC_CRP_Aerozine50_DisplayName = Aerozine50 + #LOC_CRP_AK20_DisplayName = AK20 + #LOC_CRP_AK27_DisplayName = AK27 + #LOC_CRP_Aniline_DisplayName = Anilina + #LOC_CRP_AvGas_DisplayName = AvGas + #LOC_CRP_CaveaB_DisplayName = CaveaB + #LOC_CRP_ClF3_DisplayName = ClF3 + #LOC_CRP_ClF5_DisplayName = ClF5 + #LOC_CRP_Diborane_DisplayName = Diborano + #LOC_CRP_Ethane_DisplayName = Etano + #LOC_CRP_Ethanol_DisplayName = Etanol + #LOC_CRP_Ethanol75_DisplayName = Etanol75 + #LOC_CRP_Ethanol90_DisplayName = Etanol90 + #LOC_CRP_Ethylene_DisplayName = Etileno + #LOC_CRP_FLOX30_DisplayName = FLOX30 + #LOC_CRP_FLOX70_DisplayName = FLOX70 + #LOC_CRP_FLOX88_DisplayName = FLOX88 + #LOC_CRP_Furfuryl_DisplayName = Furfuril + #LOC_CRP_Helium_DisplayName = Hélio + #LOC_CRP_HNIW_DisplayName = HNIW + #LOC_CRP_HTP_DisplayName = HTP + #LOC_CRP_HTPB_DisplayName = HTPB + #LOC_CRP_Hydrazine_DisplayName = Hidrazina + #LOC_CRP_Hydyne_DisplayName = Hydyne + #LOC_CRP_IRFNA-III_DisplayName = IRFNA-III + #LOC_CRP_IRFNA-IV_DisplayName = IRFNA-IV + #LOC_CRP_IWFNA_DisplayName = IWFNA + #LOC_CRP_Kerosene_DisplayName = Querosene + #LOC_CRP_LeadBallast_DisplayName = Lastro de Chumbo + #LOC_CRP_LqdFluorine_DisplayName = FlúorLqd + #LOC_CRP_LqdMethane_DisplayName = MetanoLqd + #LOC_CRP_LqdOxygen_DisplayName = OxigênioLqd + #LOC_CRP_Methane_DisplayName = Metano + #LOC_CRP_Methanol_DisplayName = Metanol + #LOC_CRP_MMH_DisplayName = MMH + #LOC_CRP_MON1_DisplayName = MON1 + #LOC_CRP_MON3_DisplayName = MON3 + #LOC_CRP_MON10_DisplayName = MON10 + #LOC_CRP_MON15_DisplayName = MON15 + #LOC_CRP_MON20_DisplayName = MON20 + #LOC_CRP_MON25_DisplayName = MON25 + #LOC_CRP_NGNC_DisplayName = NGNC + #LOC_CRP_N2F4_DisplayName = N2F4 + #LOC_CRP_Nitrogen_DisplayName = Nitrogênio + #LOC_CRP_NitrousOxide_DisplayName = Óxido Nitroso + #LOC_CRP_NTO_DisplayName = NTO + #LOC_CRP_OF2_DisplayName = OF2 + #LOC_CRP_PBAN_DisplayName = PBAN + #LOC_CRP_Pentaborane_DisplayName = Pentaborano + #LOC_CRP_PSPC_DisplayName = PSPC + #LOC_CRP_Syntin_DisplayName = Syntin + #LOC_CRP_TEATEB_DisplayName = TEATEB + #LOC_CRP_Tonka250_DisplayName = Tonka250 + #LOC_CRP_Tonka500_DisplayName = Tonka500 + #LOC_CRP_UDMH_DisplayName = UDMH + #LOC_CRP_UH25_DisplayName = UH25 + //DeepFreeze + #LOC_CRP_Glykerol_DisplayName = Glicerol + } +} diff --git a/Distribution/GameData/CommunityResourcePack/Localization/ru.cfg b/Distribution/GameData/CommunityResourcePack/Localization/ru.cfg new file mode 100644 index 0000000..ef6be2e --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/ru.cfg @@ -0,0 +1,236 @@ +Localization +{ + ru + { + //USI & TAC LS + #LOC_CRP_Hydrates_DisplayName = Гидраты + #LOC_CRP_Gypsum_DisplayName = Гипс + #LOC_CRP_IntakeLqd_DisplayName = Забортная жидкость + #LOC_CRP_ColonySupplies_DisplayName = Колониальные припасы + #LOC_CRP_Lead_DisplayName = Свинец + #LOC_CRP_CarbonDioxide_DisplayName = Углекислый газ + #LOC_CRP_Chemicals_DisplayName = Химикаты + #LOC_CRP_Dirt_DisplayName = Грунт + #LOC_CRP_ExoticMinerals_DisplayName = Экзотические минералы + #LOC_CRP_Food_DisplayName = Еда + #LOC_CRP_Supplies_DisplayName = Припасы + #LOC_CRP_Fertilizer_DisplayName = Удобрения + #LOC_CRP_Mulch_DisplayName = Мульча + #LOC_CRP_Machinery_DisplayName = Машинерия + #LOC_CRP_SpecializedParts_DisplayName = Специальные компоненты + #LOC_CRP_Recyclables_DisplayName = Вторсырьё + #LOC_CRP_Hydrogen_DisplayName = Водород + #LOC_CRP_Karbonite_DisplayName = Карбонит + #LOC_CRP_Karborundum_DisplayName = Карборунд + #LOC_CRP_LqdCO2_DisplayName = жидк. CO2 + #LOC_CRP_LqdCO_DisplayName = жидк. CO + #LOC_CRP_MaterialKits_DisplayName = Конструкционные материалы + #LOC_CRP_Metals_DisplayName = Металлы + #LOC_CRP_Minerals_DisplayName = Минералы + #LOC_CRP_MetallicOre_DisplayName = Металлическая руда + #LOC_CRP_Organics_DisplayName = Органика + #LOC_CRP_Oxygen_DisplayName = Кислород + #LOC_CRP_Polymers_DisplayName = Полимеры + #LOC_CRP_RareMetals_DisplayName = Редкие металлы + #LOC_CRP_RefinedExotics_DisplayName = Аффинированная экзотика + #LOC_CRP_Rock_DisplayName = Камень + #LOC_CRP_RocketParts_DisplayName = Ракетные запчасти + #LOC_CRP_SpareParts_DisplayName = Запчасти + #LOC_CRP_Substrate_DisplayName = Субстрат + #LOC_CRP_Uraninite_DisplayName = Урановая смолка // Possible variants: "Настуран" (obsolete) or "Уранинит" (looks like typo in "Уранит") + #LOC_CRP_Waste_DisplayName = Отходы + #LOC_CRP_WasteWater_DisplayName = Грязная вода + #LOC_CRP_Water_DisplayName = Вода + //NFT + #LOC_CRP_ArgonGas_DisplayName = Аргон + #LOC_CRP_ArgonGas_Abbreviation = Ar + #LOC_CRP_Boron_DisplayName = Бор + #LOC_CRP_Boron_Abbreviation = B + #LOC_CRP_ResourceLode_DisplayName = Ресурсный самородок // Literally - "resource nugget" It's a movable thing! + #LOC_CRP_EnrichedUranium_DisplayName = Обогащённый Уран + #LOC_CRP_EnrichedUranium_Abbreviation = обгщ.U + #LOC_CRP_DepletedUranium_DisplayName = Обеднённый уран + #LOC_CRP_DepletedUranium_Abbreviation = обдн.U + #LOC_CRP_LqdHydrogen_DisplayName = Жидкий водород + #LOC_CRP_LqdHydrogen_Abbreviation = ЖВ + #LOC_CRP_StoredCharge_DisplayName = Накопленный заряд + #LOC_CRP_StoredCharge_Abbreviation = НЗ + //KSPI-E + #LOC_CRP_Actinides_DisplayName = Актиноиды + #LOC_CRP_Actinides_Abbreviation = Акт + #LOC_CRP_Aluminium_DisplayName = Алюминий + #LOC_CRP_Aluminium_Abbreviation = Al + #LOC_CRP_Alumina_DisplayName = Глинозём + #LOC_CRP_Alumina_Abbreviation = Al2O3 + #LOC_CRP_Ammonia_DisplayName = Аммиак + #LOC_CRP_Ammonia_Abbreviation = NH3 + #LOC_CRP_Antimatter_DisplayName = Антиматерия + #LOC_CRP_Antimatter_Abbreviation = АМ + #LOC_CRP_LqdArgon_DisplayName = Жидкий аргон + #LOC_CRP_LqdArgon_Abbreviation = Ar + #LOC_CRP_Borate_DisplayName = Борат + #LOC_CRP_Borate_Abbreviation = Брт + #LOC_CRP_Caesium_DisplayName = Цезий + #LOC_CRP_Caesium_Abbreviation = Cs + #LOC_CRP_CarbonMonoxide_DisplayName = Угарный газ + #LOC_CRP_CarbonMonoxide_Abbreviation = CO + #LOC_CRP_Carbon_DisplayName = Углерод + #LOC_CRP_Carbon_Abbreviation = C + #LOC_CRP_ChargedParticles_DisplayName = Заряженные частицы + #LOC_CRP_ChargedParticles_Abbreviation = ЗЧ + #LOC_CRP_Chlorine_DisplayName = Хлор + #LOC_CRP_Chlorine_Abbreviation = Cl + #LOC_CRP_Decaborane_DisplayName = Декаборан // Possible variant "Декаборан(14)" though it's the same shit. + #LOC_CRP_Decaborane_Abbreviation = B10H14 + #LOC_CRP_Deuterium_DisplayName = Дейтерий + #LOC_CRP_Deuterium_Abbreviation = D + #LOC_CRP_LqdDeuterium_DisplayName = Жидкий дейтерий + #LOC_CRP_LqdDeuterium_Abbreviation = D + #LOC_CRP_DepletedFuel_DisplayName = Обеднённое топливо + #LOC_CRP_DepletedFuel_Abbreviation = обдн.Т + #LOC_CRP_ExoticMatter_DisplayName = Экзотическая материя + #LOC_CRP_ExoticMatter_Abbreviation = ЭкзМ + #LOC_CRP_FusionPellets_DisplayName = Термоядерные пеллеты // Placeholder. Suggest something better if you are a nuclear physicist. + #LOC_CRP_Fluorine_DisplayName = Фтор + #LOC_CRP_Fluorine_Abbreviation = F + #LOC_CRP_HeavyWater_DisplayName = Тяжёлая вода + #LOC_CRP_HeavyWater_Abbreviation = D20 + #LOC_CRP_IntakeAtm_DisplayName = Атмосферные газы + #LOC_CRP_IntakeAtm_Abbreviation = АтмГ + #LOC_CRP_KryptonGas_DisplayName = Криптон + #LOC_CRP_KryptonGas_Abbreviation = Kr + #LOC_CRP_LqdKrypton_DisplayName = Жидкий криптон + #LOC_CRP_LqdKrypton_Abbreviation = Kr + #LOC_CRP_NeonGas_DisplayName = Неон + #LOC_CRP_NeonGas_Abbreviation = Ne + #LOC_CRP_LqdNeon_DisplayName = Жидкий неон + #LOC_CRP_LqdNeon_Abbreviation = Ne + #LOC_CRP_Lithium_DisplayName = Литий + #LOC_CRP_Lithium_Abbreviation = Li + #LOC_CRP_Lithium6_DisplayName = Литий-6 + #LOC_CRP_Lithium6_Abbreviation = Li6 + #LOC_CRP_LithiumHydride_DisplayName = Гидрид лития + #LOC_CRP_LithiumHydride_Abbreviation = LiH + #LOC_CRP_LithiumHydride_Title = Гидрид лития + #LOC_CRP_LithiumDeuteride_DisplayName = Дейтерид лития + #LOC_CRP_LithiumDeuteride_Abbreviation = Li6D + #LOC_CRP_LithiumDeuteride_Title = Дейтерид лития + #LOC_CRP_LqdAmmonia_DisplayName = Жидкий аммиак + #LOC_CRP_LqdAmmonia_Abbreviation = NH3 + #LOC_CRP_Helium3_DisplayName = Гелий-3 + #LOC_CRP_Helium3_Abbreviation = He3 + #LOC_CRP_LqdHe3_DisplayName = Жидкий гелий-3 + #LOC_CRP_LqdHe3_Abbreviation = He3 + #LOC_CRP_Helium4_DisplayName = Гелий-4 + #LOC_CRP_Helium4_Abbreviation = He4 + #LOC_CRP_LqdHelium_DisplayName = Жидкий гелий + #LOC_CRP_LqdHelium_Abbreviation = He4 + #LOC_CRP_Nitratine_DisplayName = Натриевая селитра + #LOC_CRP_Nitratine_Title = Натриевая селитра + #LOC_CRP_Hexaborane_DisplayName = Гексаборан // Possible variant is "Гексаборан(10)" though it's the default meaning anyway. + #LOC_CRP_LqdNitrogen_DisplayName = Жидкий азот + #LOC_CRP_LqdNitrogen_Abbreviation = N14 + #LOC_CRP_LqdNitrogen15_DisplayName = Жидкий азот-15 + #LOC_CRP_LqdNitrogen15_Abbreviation = N15 + #LOC_CRP_Megajoules_DisplayName = Мегаджоули + #LOC_CRP_Megajoules_Abbreviation = МДж + #LOC_CRP_Monazite_DisplayName = Монацит + #LOC_CRP_Monazite_Abbreviation = Мнцт + #LOC_CRP_LqdOxygen18_DisplayName = Жидкий кислород-18 + #LOC_CRP_LqdOxygen18_Abbreviation = O18 + #LOC_CRP_Sodium_DisplayName = Натрий + #LOC_CRP_Sodium_Abbreviation = Na + #LOC_CRP_PolyvinylChloride_DisplayName = Поливинилхлорид + #LOC_CRP_PolyvinylChloride_Abbreviation = ПВХ + #LOC_CRP_Plutonium-238_DisplayName = Плутоний-238 + #LOC_CRP_Plutonium-238_Abbreviation = Pu238 + #LOC_CRP_Regolith_DisplayName = Реголит + #LOC_CRP_Regolith_Abbreviation = Р + #LOC_CRP_UF4_DisplayName = Тетрафторид урана + #LOC_CRP_UF4_Abbreviation = UF4 + #LOC_CRP_Silicates_DisplayName = Силикаты + #LOC_CRP_Silicates_Abbreviation = Сил + #LOC_CRP_Silicon_DisplayName = Кремний + #LOC_CRP_Silicon_Abbreviation = Si + #LOC_CRP_SolarWind_DisplayName = Солнечный ветер + #LOC_CRP_SolarWind_Abbreviation = СВ + #LOC_CRP_ThermalPower_DisplayName = Тепловая энергия + #LOC_CRP_ThermalPower_Abbreviation = ТЭ + #LOC_CRP_Thorium_DisplayName = Торий + #LOC_CRP_ThF4_DisplayName = Тетрафторид тория + #LOC_CRP_ThF4_Abbreviation = ThF4 + #LOC_CRP_Tritium_DisplayName = Тритий + #LOC_CRP_Tritium_Abbreviation = T + #LOC_CRP_Tritium_Title = Тритий + #LOC_CRP_LqdTritium_DisplayName = Жидкий тритий + #LOC_CRP_LqdTritium_Abbreviation = T + #LOC_CRP_UraniumNitride_DisplayName = Нитрид урана + #LOC_CRP_UraniumNitride_Abbreviation = UN + #LOC_CRP_VacuumPlasma_DisplayName = Квантовый вакуум //Proper name in english is "Quantum Vacuum" or "Quantum Vacuum Virtual Plasma", rather than "Vacuum Plasma", and it's a physical effect rather than anything storeable. + #LOC_CRP_VacuumPlasma_Abbreviation = КвВ + #LOC_CRP_WasteHeat_DisplayName = Избыточное тепло + #LOC_CRP_WasteHeat_Abbreviation = Изб.Т + #LOC_CRP_LqdXenon_DisplayName = Жидкий ксенон + #LOC_CRP_LqdXenon_Abbreviation = Xe + #LOC_CRP_LqdXenon_Title = Жидкий ксенон + //RealFuels + #LOC_CRP_Aerozine50_DisplayName = Аэрозин + #LOC_CRP_AK20_DisplayName = AK20 + #LOC_CRP_AK27_DisplayName = AK27 + #LOC_CRP_Aniline_DisplayName = Анилин + #LOC_CRP_AvGas_DisplayName = Авиационный бензин + #LOC_CRP_CaveaB_DisplayName = CaveaB + #LOC_CRP_ClF3_DisplayName = Трифторид хлора + #LOC_CRP_ClF5_DisplayName = Пентафторид хлора + #LOC_CRP_Diborane_DisplayName = Диборан + #LOC_CRP_Ethane_DisplayName = Этан + #LOC_CRP_Ethanol_DisplayName = Этанол + #LOC_CRP_Ethanol75_DisplayName = Этанол 75% + #LOC_CRP_Ethanol90_DisplayName = Этанол 90% + #LOC_CRP_Ethylene_DisplayName = Этилен + #LOC_CRP_FLOX30_DisplayName = FLOX30 + #LOC_CRP_FLOX70_DisplayName = FLOX70 + #LOC_CRP_FLOX88_DisplayName = FLOX88 + #LOC_CRP_Furfuryl_DisplayName = Фурфуриловый спирт + #LOC_CRP_Helium_DisplayName = Гелий + #LOC_CRP_HNIW_DisplayName = HNIW // "Гексанитрогексаазаизовюрцитан" is too long, no? + #LOC_CRP_HTP_DisplayName = Пероксид водорода + #LOC_CRP_HTPB_DisplayName = HTPB // "Полибутадиен с концевыми гидроксильными группами" is too long, no? + #LOC_CRP_Hydrazine_DisplayName = Гидразин + #LOC_CRP_Hydyne_DisplayName = Гидин + #LOC_CRP_IRFNA-III_DisplayName = IRFNA-III + #LOC_CRP_IRFNA-IV_DisplayName = IRFNA-IV + #LOC_CRP_IWFNA_DisplayName = IWFNA + #LOC_CRP_Kerosene_DisplayName = Керосин + #LOC_CRP_LeadBallast_DisplayName = Свинцовый балласт + #LOC_CRP_LqdFluorine_DisplayName = Жидкий фтор + #LOC_CRP_LqdMethane_DisplayName = Жидкий метан + #LOC_CRP_LqdOxygen_DisplayName = Жидкий кислород + #LOC_CRP_Methane_DisplayName = Метан + #LOC_CRP_Methanol_DisplayName = Метанол + #LOC_CRP_MMH_DisplayName = Монометилгидразин + #LOC_CRP_MON1_DisplayName = MON1 + #LOC_CRP_MON3_DisplayName = MON3 + #LOC_CRP_MON10_DisplayName = MON10 + #LOC_CRP_MON15_DisplayName = MON15 + #LOC_CRP_MON20_DisplayName = MON20 + #LOC_CRP_MON25_DisplayName = MON25 + #LOC_CRP_NGNC_DisplayName = NGNC // "Нитроглицерин/Нитроцеллюлоза" is too long, no? + #LOC_CRP_N2F4_DisplayName = Тетрафторгидразин + #LOC_CRP_Nitrogen_DisplayName = Азот + #LOC_CRP_NitrousOxide_DisplayName = Оксид диазота + #LOC_CRP_NTO_DisplayName = Тетраоксид азота + #LOC_CRP_OF2_DisplayName = Дифторид кислорода + #LOC_CRP_PBAN_DisplayName = Перхлорат аммония + #LOC_CRP_Pentaborane_DisplayName = Пентаборан + #LOC_CRP_PSPC_DisplayName = PSPC // Don't know this mark of solid fuel. + #LOC_CRP_Syntin_DisplayName = Синтин + #LOC_CRP_TEATEB_DisplayName = Триэтилборан + #LOC_CRP_Tonka250_DisplayName = Tonka250 + #LOC_CRP_Tonka500_DisplayName = Tonka500 + #LOC_CRP_UDMH_DisplayName = Несимметричный диметилгидразин + #LOC_CRP_UH25_DisplayName = UH25 + //DeepFreeze + #LOC_CRP_Glykerol_DisplayName = Гликерол // It's a fantastic spirit-like cryogenic fluid rather than a typo in common glycerine. + } +} diff --git a/Distribution/GameData/CommunityResourcePack/Localization/zh-cn.cfg b/Distribution/GameData/CommunityResourcePack/Localization/zh-cn.cfg new file mode 100644 index 0000000..28e8dc4 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/Localization/zh-cn.cfg @@ -0,0 +1,256 @@ +Localization +{ + zh-cn + { + //USI + #LOC_CRP_Hydrates_DisplayName = 水合物 + #LOC_CRP_Gypsum_DisplayName = 石膏 + #LOC_CRP_IntakeLqd_DisplayName = 摄入液体 + #LOC_CRP_ColonySupplies_DisplayName = 殖民地用品 + #LOC_CRP_Lead_DisplayName = 鉛者 + #LOC_CRP_CarbonDioxide_DisplayName = 二氧化碳 + #LOC_CRP_Chemicals_DisplayName = 化学制品 + #LOC_CRP_Dirt_DisplayName = 污垢 + #LOC_CRP_ExoticMinerals_DisplayName = 奇异矿物 + #LOC_CRP_Food_DisplayName = 食物 + #LOC_CRP_Supplies_DisplayName = 资源 + #LOC_CRP_Fertilizer_DisplayName = 肥料 + #LOC_CRP_Mulch_DisplayName = 护根 + #LOC_CRP_Machinery_DisplayName = 机械 + #LOC_CRP_SpecializedParts_DisplayName = 专业零件 + #LOC_CRP_Recyclables_DisplayName = 可回收 + #LOC_CRP_Hydrogen_DisplayName = 气态氢 + #LOC_CRP_Karbonite_DisplayName = Karbonite + #LOC_CRP_Karborundum_DisplayName = Karborundum + #LOC_CRP_LqdCO2_DisplayName = 液态二氧化碳 + #LOC_CRP_LqdCO_DisplayName = 液态一氧化碳 + #LOC_CRP_MaterialKits_DisplayName = 材料套装 + #LOC_CRP_Metals_DisplayName = 金属 + #LOC_CRP_Minerals_DisplayName = 矿产 + #LOC_CRP_MetallicOre_DisplayName = 金属矿物 + #LOC_CRP_Organics_DisplayName = 有机物 + #LOC_CRP_Oxygen_DisplayName = 气态氧 + #LOC_CRP_Polymers_DisplayName = 聚合物 + #LOC_CRP_RareMetals_DisplayName = 稀有金属 + #LOC_CRP_RefinedExotics_DisplayName = 精炼奇异矿物 + #LOC_CRP_Rock_DisplayName = 石头 + #LOC_CRP_RocketParts_DisplayName = 火箭零件 + #LOC_CRP_SpareParts_DisplayName = 回收的部件 + #LOC_CRP_Substrate_DisplayName = 基质 + #LOC_CRP_Uraninite_DisplayName = 沥青铀矿 + #LOC_CRP_Waste_DisplayName = 垃圾 + #LOC_CRP_WasteWater_DisplayName = 污水 + #LOC_CRP_Water_DisplayName = 液态水 + + //NFT + #LOC_CRP_ArgonGas_DisplayName = 氩气 + #LOC_CRP_ArgonGas_Abbreviation = 氩气 + #LOC_CRP_Boron_DisplayName = 硼 + #LOC_CRP_Boron_Abbreviation = 硼 + #LOC_CRP_ResourceLode_DisplayName = ResourceLode + #LOC_CRP_EnrichedUranium_DisplayName = 富铀 + #LOC_CRP_EnrichedUranium_Abbreviation = 富铀 + #LOC_CRP_DepletedUranium_DisplayName = 贫铀 + #LOC_CRP_DepletedUranium_Abbreviation = 贫铀 + #LOC_CRP_LqdHydrogen_DisplayName = 液态氢 + #LOC_CRP_LqdHydrogen_Abbreviation = 液态氢 + #LOC_CRP_StoredCharge_DisplayName = 存储的电力 + #LOC_CRP_StoredCharge_Abbreviation = 存储的电力 + + //KSPI-E + #LOC_CRP_Actinides_DisplayName = 锕系元素 + #LOC_CRP_Actinides_Abbreviation = 锕系元素 + #LOC_CRP_Aluminium_DisplayName = 铝 + #LOC_CRP_Aluminium_Abbreviation = 铝 + #LOC_CRP_Alumina_DisplayName = 氧化铝 + #LOC_CRP_Alumina_Abbreviation = 氧化铝 + #LOC_CRP_Ammonia_DisplayName = 氨 + #LOC_CRP_Ammonia_Abbreviation = 氨 + #LOC_CRP_Antimatter_DisplayName = 反物质 + #LOC_CRP_Antimatter_Abbreviation = 反物质 + #LOC_CRP_AntiHydrogen_DisplayName = 反氢 + #LOC_CRP_AntiHydrogen_Abbreviation = 反氢 + #LOC_CRP_LqdArgon_DisplayName = 液态氩 + #LOC_CRP_LqdArgon_Abbreviation = 氩 + #LOC_CRP_Borate_DisplayName = 硼酸 + #LOC_CRP_Borate_Abbreviation = 硼酸 + #LOC_CRP_Caesium_DisplayName = 铯 + #LOC_CRP_Caesium_Abbreviation = 铯 + #LOC_CRP_Calcium_Abbreviation = 钙 + #LOC_CRP_Calcium_DisplayName = 钙 + #LOC_CRP_CarbonMonoxide_DisplayName = 一氧化碳 + #LOC_CRP_CarbonMonoxide_Abbreviation = 一氧化碳 + #LOC_CRP_Carbon_DisplayName = 碳 + #LOC_CRP_Carbon_Abbreviation = 碳 + #LOC_CRP_ChargedParticles_DisplayName = 带电粒子 + #LOC_CRP_ChargedParticles_Abbreviation = 带电粒子 + #LOC_CRP_Chlorine_DisplayName = 氯 + #LOC_CRP_Chlorine_Abbreviation = 氯 + #LOC_CRP_CompressedAir_DisplayName = 压缩空气 + #LOC_CRP_CompressedAir_Abbreviation = 压缩空气 + #LOC_CRP_Decaborane_DisplayName = 癸硼烷 + #LOC_CRP_Decaborane_Abbreviation = 癸硼烷 + #LOC_CRP_Deuterium_DisplayName = 氘 + #LOC_CRP_Deuterium_Abbreviation = 氘 + #LOC_CRP_LqdDeuterium_DisplayName = 液态氘 + #LOC_CRP_LqdDeuterium_Abbreviation = 液态氘 + #LOC_CRP_DepletedFuel_DisplayName = 核废料 + #LOC_CRP_DepletedFuel_Abbreviation = 核废料 + #LOC_CRP_ExoticMatter_DisplayName = 奇异物质 + #LOC_CRP_ExoticMatter_Abbreviation = 奇异物质 + #LOC_CRP_FusionPellets_DisplayName = 聚变燃料球 + #LOC_CRP_FusionPellets_Abbreviation = 聚变燃料球 + #LOC_CRP_Fluorine_DisplayName = 氟 + #LOC_CRP_Fluorine_Abbreviation = 氟 + #LOC_CRP_Fluorite_DisplayName = 萤石 + #LOC_CRP_Fluorite_Abbreviation = 萤石 + #LOC_CRP_HeavyWater_DisplayName = 重水 + #LOC_CRP_HeavyWater_Abbreviation = 重水 + #LOC_CRP_IntakeAtm_DisplayName = 进气 + #LOC_CRP_IntakeAtm_Abbreviation = 进气 + #LOC_CRP_KryptonGas_DisplayName = 氪气 + #LOC_CRP_KryptonGas_Abbreviation = 氪气 + #LOC_CRP_LqdKrypton_DisplayName = 液态氪 + #LOC_CRP_LqdKrypton_Abbreviation = 液态氪 + #LOC_CRP_NeonGas_DisplayName = 氖气 + #LOC_CRP_NeonGas_Abbreviation = 氖气 + #LOC_CRP_LqdNeon_DisplayName = 液态氖 + #LOC_CRP_LqdNeon_Abbreviation = 液态氖 + #LOC_CRP_Lithium_DisplayName = 锂 + #LOC_CRP_Lithium_Abbreviation = 锂 + #LOC_CRP_Lithium6_DisplayName = 锂-6 + #LOC_CRP_Lithium6_Abbreviation = 锂-6 + #LOC_CRP_LithiumHydride_DisplayName = 氢化锂 + #LOC_CRP_LithiumHydride_Abbreviation = 氢化锂 + #LOC_CRP_LithiumDeuteride_DisplayName = 氘化锂 + #LOC_CRP_LithiumDeuteride_Abbreviation = 氘化锂 + #LOC_CRP_LqdAmmonia_DisplayName = 液态氨 + #LOC_CRP_LqdAmmonia_Abbreviation = 液态氨 + #LOC_CRP_Helium3_DisplayName = 氦-3 + #LOC_CRP_Helium3_Abbreviation = 氦-3 + #LOC_CRP_LqdHe3_DisplayName = 液态氦-3 + #LOC_CRP_LqdHe3_Abbreviation = 液态氦-3 + #LOC_CRP_Helium4_DisplayName = 氦 + #LOC_CRP_Helium4_Abbreviation = 氦 + #LOC_CRP_LqdHelium_DisplayName = 液态氦 + #LOC_CRP_LqdHelium_Abbreviation = 液态氦 + #LOC_CRP_Nitratine_DisplayName = 钠硝石 + #LOC_CRP_Nitratine_Abbreviation = 钠硝石 + #LOC_CRP_Hexaborane_DisplayName = 六硼烷 + #LOC_CRP_Hexaborane_Abbreviation = 六硼烷 + #LOC_CRP_LqdNitrogen_DisplayName = 液态氮 + #LOC_CRP_LqdNitrogen_Abbreviation = 液态氮 + #LOC_CRP_LqdNitrogen15_DisplayName = 液态氮-15 + #LOC_CRP_LqdNitrogen15_Abbreviation = 液态氮-15 + #LOC_CRP_Megajoules_DisplayName = 兆焦能量 + #LOC_CRP_Megajoules_Abbreviation = 兆焦能量 + #LOC_CRP_Mopedantte_DisplayName = 独居石 + #LOC_CRP_Mopedantte_Abbreviation = 独居石 + #LOC_CRP_LqdOxygen18_DisplayName = 液态氧-18 + #LOC_CRP_LqdOxygen18_Abbreviation = 液态氧-18 + #LOC_CRP_Salt_DisplayName = 盐 + #LOC_CRP_Salt_Abbreviation = 盐 + #LOC_CRP_Sodium_DisplayName = 钠 + #LOC_CRP_Sodium_Abbreviation = 钠 + #LOC_CRP_Sulphur_DisplayName = 硫 + #LOC_CRP_Sulphur_Abbreviation = 硫 + #LOC_CRP_SolidHydrogen_DisplayName = 固态氢 + #LOC_CRP_SolidHydrogen_Abbreviation = 固态氢 + #LOC_CRP_PolyvinylChloride_DisplayName = 聚氯乙烯 + #LOC_CRP_PolyvinylChloride_Abbreviation = PVC + #LOC_CRP_Plutonium-238_DisplayName = 钚-238 + #LOC_CRP_Plutonium-238_Abbreviation = 钚-238 + #LOC_CRP_Regolith_DisplayName = 浮土 + #LOC_CRP_Regolith_Abbreviation = 浮土 + #LOC_CRP_UF4_DisplayName = 四氟化鈾 + #LOC_CRP_UF4_Abbreviation = 四氟化鈾 + #LOC_CRP_Silicates_DisplayName = 硅酸盐 + #LOC_CRP_Silicates_Abbreviation = 硅酸盐 + #LOC_CRP_Silicon_DisplayName = 硅 + #LOC_CRP_Silicon_Abbreviation = 硅 + #LOC_CRP_Spodumene_DisplayName = 锂辉石 + #LOC_CRP_Spodumene_Abbreviation = 锂辉石 + #LOC_CRP_SolarWind_DisplayName = 太阳风 + #LOC_CRP_SolarWind_Abbreviation = 太阳风 + #LOC_CRP_ThermalPower_DisplayName = 热能 + #LOC_CRP_ThermalPower_Abbreviation = 热能 + #LOC_CRP_Thorium_DisplayName = 钍 + #LOC_CRP_Thorium_Abbreviation = 钍 + #LOC_CRP_ThF4_DisplayName = 四氟化钍 + #LOC_CRP_ThF4_Abbreviation = 四氟化钍 + #LOC_CRP_Tritium_DisplayName = 氚 + #LOC_CRP_Tritium_Abbreviation = 氚 + #LOC_CRP_LqdTritium_DisplayName = 液态氚 + #LOC_CRP_LqdTritium_Abbreviation = 液态氚 + #LOC_CRP_UraniumNitride_DisplayName = 氮化铀 + #LOC_CRP_UraniumNitride_Abbreviation = 氮化铀 + #LOC_CRP_VacuumPlasma_DisplayName = 真空等离子体 + #LOC_CRP_VacuumPlasma_Abbreviation = 真空等离子体 + #LOC_CRP_WasteHeat_DisplayName = 废热 + #LOC_CRP_WasteHeat_Abbreviation = 废热 + #LOC_CRP_LqdXenon_DisplayName = 液态氙 + #LOC_CRP_LqdXenon_Abbreviation = 液态氙 + + //RealFuels + #LOC_CRP_Aerozine50_DisplayName = Aerozine50 + #LOC_CRP_AK20_DisplayName = AK20 + #LOC_CRP_AK27_DisplayName = AK27 + #LOC_CRP_Aniline_DisplayName = 苯胺 + #LOC_CRP_AvGas_DisplayName = AvGas + #LOC_CRP_CaveaB_DisplayName = CaveaB + #LOC_CRP_ClF3_DisplayName = ClF3 + #LOC_CRP_ClF5_DisplayName = ClF5 + #LOC_CRP_Diborane_DisplayName = 乙硼烷 + #LOC_CRP_Ethane_DisplayName = 乙烷 + #LOC_CRP_Ethanol_DisplayName = 乙醇 + #LOC_CRP_Ethanol75_DisplayName = 乙醇75 + #LOC_CRP_Ethanol90_DisplayName = 乙醇90 + #LOC_CRP_Ethylene_DisplayName = 乙烯 + #LOC_CRP_FLOX30_DisplayName = FLOX30 + #LOC_CRP_FLOX70_DisplayName = FLOX70 + #LOC_CRP_FLOX88_DisplayName = FLOX88 + #LOC_CRP_Furfuryl_DisplayName = 糠醇 + #LOC_CRP_Helium_DisplayName = 氦气 + #LOC_CRP_HNIW_DisplayName = 六硝基六氮杂异伍兹烷 + #LOC_CRP_HTP_DisplayName = 过氧化氢 + #LOC_CRP_HTPB_DisplayName = 端羟基聚丁二烯 + #LOC_CRP_Hydrazine_DisplayName = 联氨 + #LOC_CRP_Hydyne_DisplayName = Hydyne + #LOC_CRP_IRFNA-III_DisplayName = 红发烟硝酸-3 + #LOC_CRP_IRFNA-IV_DisplayName = 红发烟硝酸-4 + #LOC_CRP_IWFNA_DisplayName = 白发烟硝酸 + #LOC_CRP_Kerosene_DisplayName = 煤油 + #LOC_CRP_LeadBallast_DisplayName = 铅镇流器 + #LOC_CRP_LqdFluorine_DisplayName = 液态氟 + #LOC_CRP_LqdMethane_DisplayName = 液态甲烷 + #LOC_CRP_LqdOxygen_DisplayName = 液态氧 + #LOC_CRP_Methane_DisplayName = 甲烷 + #LOC_CRP_Methanol_DisplayName = 甲醇 + #LOC_CRP_MMH_DisplayName = 甲肼 + #LOC_CRP_MON1_DisplayName = MON1 + #LOC_CRP_MON3_DisplayName = MON3 + #LOC_CRP_MON10_DisplayName = MON10 + #LOC_CRP_MON15_DisplayName = MON15 + #LOC_CRP_MON20_DisplayName = MON20 + #LOC_CRP_MON25_DisplayName = MON25 + #LOC_CRP_NGNC_DisplayName = NGNC + #LOC_CRP_N2F4_DisplayName = 四氟肼 + #LOC_CRP_Nitrogen_DisplayName = 液态氮 + #LOC_CRP_NitrousOxide_DisplayName = 一氧化氮 + #LOC_CRP_NTO_DisplayName = 四氧化二氮 + #LOC_CRP_OF2_DisplayName = 二氟化氧 + #LOC_CRP_PBAN_DisplayName = 聚丁二烯丙烯腈 + #LOC_CRP_Pentaborane_DisplayName = 戊硼烷 + #LOC_CRP_PSPC_DisplayName = PSPC + #LOC_CRP_Syntin_DisplayName = Syntin + #LOC_CRP_TEATEB_DisplayName = TEATEB + #LOC_CRP_Tonka250_DisplayName = 通卡250 + #LOC_CRP_Tonka500_DisplayName = 通卡500 + #LOC_CRP_UDMH_DisplayName = 偏二甲肼 + #LOC_CRP_UH25_DisplayName = UH25 + + + //DeepFreeze + #LOC_CRP_Glykerol_DisplayName = 甘油 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Alumina.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Alumina.cfg new file mode 100644 index 0000000..1594ad6 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Alumina.cfg @@ -0,0 +1,351 @@ +// +// Community Resource Pack +// Resource: Alumina +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +// ####################### Bodys with NO Alumina (Sun, Jool, Vall, Pol) +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Sun + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE // See Biome definitions +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Minmus + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Jool + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Vall + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Pol + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +// ####################### Global definition of Alumina +GLOBAL_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + Distribution + { + PresenceChance = 80 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +// ####################### Planetary definition of Alumina +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Moho + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 5 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Eve + Distribution + { + PresenceChance = 100 + MinAbundance = 0.5 + MaxAbundance = 8 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Gilly + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 5 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Kerbin + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Mun + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Minmus; See Biome definition. +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Duna + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 3 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Ike + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Dres + Distribution + { + PresenceChance = 100 + MinAbundance = 0.5 + MaxAbundance = 6 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Jool here (GasGiant); Alumina prevented, see top. +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.01 + MaxAbundance = 1 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Tylo + + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Vall; Alumina prevented, see top. +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Bop + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 5 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Pol; Alumina prevented, see top. +PLANETARY_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Eeloo + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 3 + Variance = 50 + Dispersal = 3 + } +} +// ####################### Biome definition of Alumina +// ##### Minmus. All white areas. +BIOME_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Minmus + BiomeName = Poles + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 7 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Minmus + BiomeName = Highlands + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 7 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Minmus + BiomeName = Midlands + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 7 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Minmus + BiomeName = Lowlands + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 7 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Alumina + ResourceType = 0 + PlanetName = Minmus + BiomeName = Slopes + Distribution + { + PresenceChance = 100 + MinAbundance = 0.01 + MaxAbundance = 3 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Antimatter.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Antimatter.cfg new file mode 100644 index 0000000..c269fc9 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Antimatter.cfg @@ -0,0 +1,50 @@ +// +// Community Resource Pack +// Resource: Antimatter +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +// Kerbin Exo +PLANETARY_RESOURCE +{ + ResourceName = Antimatter + ResourceType = 3 + PlanetName = Kerbin + Distribution + { + PresenceChance = 100 + MinAbundance = 0.001 // - Relative atmospheric scaling applied + MaxAbundance = 0.002 // - Relative atmospheric scaling applied + MinAltitude = 1 + MaxAltitude = 2 + MinRange = 0.25 + MaxRange = 0.3 + Variance = 0 + } +} + +// Jool exo +PLANETARY_RESOURCE +{ + ResourceName = Antimatter + ResourceType = 3 + PlanetName = Jool + Distribution + { + PresenceChance = 100 + MinAbundance = 50 // - Relative atmospheric scaling applied + MaxAbundance = 100 // - Relative atmospheric scaling applied + MinAltitude = 1 + MaxAltitude = 3 + MinRange = 1 + MaxRange = 1 + Variance = 0 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/ArgonGas.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/ArgonGas.cfg new file mode 100644 index 0000000..c30ef92 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/ArgonGas.cfg @@ -0,0 +1,67 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +GLOBAL_RESOURCE +{ + ResourceName = ArgonGas + ResourceType = 2 + + Distribution + { + PresenceChance = 50 + MinAbundance = 1 // 0.001 - Relative atmospheric scaling applied + MaxAbundance = 100 // 0.5 - Relative atmospheric scaling applied + Variance = 5 + } +} +PLANETARY_RESOURCE +{ + ResourceName = ArgonGas + ResourceType = 2 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 // 0.01 - Relative atmospheric scaling applied + MaxAbundance = 10 // 0.1 - Relative atmospheric scaling applied + Variance = 5 + } +} +PLANETARY_RESOURCE +{ + ResourceName = ArgonGas + ResourceType = 2 + PlanetName = Duna + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 // 0.001 - Relative atmospheric scaling applied + MaxAbundance = 1 // 0.01 - Relative atmospheric scaling applied + Variance = 5 + } +} +PLANETARY_RESOURCE +{ + ResourceName = ArgonGas + ResourceType = 2 + PlanetName = Jool + + Distribution + { + PresenceChance = 100 + MinAbundance = 7 // 0.07 - Relative atmospheric scaling applied + MaxAbundance = 100 // 1 - Relative atmospheric scaling applied + Variance = 5 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/CarbonDioxide.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/CarbonDioxide.cfg new file mode 100644 index 0000000..83d22d8 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/CarbonDioxide.cfg @@ -0,0 +1,68 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +PLANETARY_RESOURCE +{ + ResourceName = CarbonDioxide + ResourceType = 2 + PlanetName = Eve + + Distribution + { + PresenceChance = 100 + MinAbundance = 97 // 95 - Relative atmospheric scaling applied + MaxAbundance = 100 // 97 - Relative atmospheric scaling applied + Variance = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = CarbonDioxide + ResourceType = 2 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 // 1 - Relative atmospheric scaling applied + MaxAbundance = 2 // 2 - Relative atmospheric scaling applied + Variance = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = CarbonDioxide + ResourceType = 2 + PlanetName = Duna + + Distribution + { + PresenceChance = 100 + MinAbundance = 97 // 95 - Relative atmospheric scaling applied + MaxAbundance = 100 // 97 - Relative atmospheric scaling applied + Variance = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = CarbonDioxide + ResourceType = 2 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 5 // 5 - Relative atmospheric scaling applied + MaxAbundance = 11 // 10 - Relative atmospheric scaling applied + Variance = 0 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Dirt.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Dirt.cfg new file mode 100644 index 0000000..7b92187 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Dirt.cfg @@ -0,0 +1,42 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +PLANETARY_RESOURCE +{ + ResourceName = Dirt + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Dirt + ResourceType = 0 + + Distribution + { + PresenceChance = 100 + MinAbundance =20 + MaxAbundance = 50 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/ExoticMinerals.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/ExoticMinerals.cfg new file mode 100644 index 0000000..3a9a87b --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/ExoticMinerals.cfg @@ -0,0 +1,42 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +PLANETARY_RESOURCE +{ + ResourceName = ExoticMinerals + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = ExoticMinerals + ResourceType = 0 + + Distribution + { + PresenceChance = 50 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 10 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Gypsum.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Gypsum.cfg new file mode 100644 index 0000000..1b18dac --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Gypsum.cfg @@ -0,0 +1,58 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +PLANETARY_RESOURCE +{ + ResourceName = Gypsum + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Gypsum + ResourceType = 0 + + Distribution + { + PresenceChance = 70 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Gypsum + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Hydrates.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Hydrates.cfg new file mode 100644 index 0000000..cebabad --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Hydrates.cfg @@ -0,0 +1,58 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +PLANETARY_RESOURCE +{ + ResourceName = Hydrates + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Hydrates + ResourceType = 0 + + Distribution + { + PresenceChance = 80 + MinAbundance = .1 + MaxAbundance = 25 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Hydrates + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .1 + MaxAbundance = 25 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/IntakeLqd.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/IntakeLqd.cfg new file mode 100644 index 0000000..9a927cb --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/IntakeLqd.cfg @@ -0,0 +1,27 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +GLOBAL_RESOURCE +{ + ResourceName = IntakeLqd + ResourceType = 1 + + Distribution + { + PresenceChance = 100 + MinAbundance = 100 + MaxAbundance = 100 + Variance = 20 + Dispersal = 3 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Karbonite.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Karbonite.cfg new file mode 100644 index 0000000..c12057b --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Karbonite.cfg @@ -0,0 +1,197 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +GLOBAL_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 0 + + Distribution + { + PresenceChance = 70 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 1 + + Distribution + { + PresenceChance = 80 + MinAbundance = 5 // 1 - Relative atmospheric scaling applied + MaxAbundance = 50 // 10 - Relative atmospheric scaling applied + Variance = 20 + Dispersal = 3 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 2 + + Distribution + { + PresenceChance = 80 + MinAbundance = .001 + MaxAbundance = 5 // 1 - Relative atmospheric scaling applied + Variance = 50 //Karbonite plumes venting + Dispersal = 3 + } +} +GLOBAL_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 3 + + Distribution + { + PresenceChance = 20 + MinAbundance = .001 + MaxAbundance = 50 // 0.5 - Relative atmospheric scaling applied + MinAltitude = .2 + MaxAltitude = 2 + MinRange = .01 + MaxRange = .5 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 2 + PlanetName = Jool + + Distribution + { + PresenceChance = 100 + MinAbundance = 100 // 80 - Relative atmospheric scaling applied + MaxAbundance = 100 // 80 - Relative atmospheric scaling applied + Variance = 50 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 1 + PlanetName = Eve + + Distribution + { + PresenceChance = 100 + MinAbundance = 75 // 60 - Relative atmospheric scaling applied + MaxAbundance = 75 //60 - Relative atmospheric scaling applied + Variance = 10 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 2 + MaxAbundance = 2 + Variance = 10 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 1 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 + MaxAbundance = .001 + Variance = 10 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 2 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 + MaxAbundance = .001 + Variance = 10 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 3 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 // 0.001 - Relative atmospheric scaling applied + MaxAbundance = .001 // 0.001 - Relative atmospheric scaling applied + MinAltitude = .245 + MaxAltitude = .245 + MinRange = .01 + MaxRange = .01 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = Karbonite + ResourceType = 3 + PlanetName = Jool + + Distribution + { + PresenceChance = 100 + MinAbundance = 100 // 1 - Relative atmospheric scaling applied + MaxAbundance = 100 // 1 - Relative atmospheric scaling applied + MinAltitude = .1 + MaxAltitude = .1 + MinRange = .1 + MaxRange = .1 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Karborundum.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Karborundum.cfg new file mode 100644 index 0000000..db423bd --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Karborundum.cfg @@ -0,0 +1,77 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +PLANETARY_RESOURCE +{ + ResourceName = Karborundum + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = Karborundum + ResourceType = 0 + PlanetName = Eve + + Distribution + { + PresenceChance = 100 + MinAbundance = 10 + MaxAbundance = 50 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Karborundum + ResourceType = 0 + PlanetName = Eeloo + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Karborundum + ResourceType = 3 + PlanetName = Sun + + Distribution + { + PresenceChance = 100 + MinAbundance = 10 + MaxAbundance = 100 + MinAltitude = 40 + MaxAltitude = 40 + MinRange = 5 + MaxRange = 5 + Variance = 50 + } +} + diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdDeuterium.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdDeuterium.cfg new file mode 100644 index 0000000..628101e --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdDeuterium.cfg @@ -0,0 +1,28 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +// Jool atmo +PLANETARY_RESOURCE +{ + ResourceName = LqdDeuterium + ResourceType = 2 + PlanetName = Jool + + Distribution + { + PresenceChance = 100 + MinAbundance = 20 // - Relative atmospheric scaling applied + MaxAbundance = 100 // - Relative atmospheric scaling applied + Variance = 20 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdHe3.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdHe3.cfg new file mode 100644 index 0000000..d79f13d --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdHe3.cfg @@ -0,0 +1,220 @@ +// +// +// Resource: LqdHe3 +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +//Default : Crustal ranges between Kerbin and Mun +GLOBAL_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 0 + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.00000000000037 + MaxAbundance = 0.0000000067 + Variance = 0 + Dispersal = 1 + } +} + +// Kerbin Crustal Helium3 abundance is 10 times Earth abundance +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.00000000000037 + MaxAbundance = 0.00000000000037 + Variance = 0 + Dispersal = 1 + } +} + +// Earth crust contains 0.000145% of Helium3 compaired to atmosphere +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 0 + PlanetName = Earth + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.000000000000037 + MaxAbundance = 0.000000000000037 + Variance = 0 + Dispersal = 1 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 0 + PlanetName = Mun + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.00000000067 + MaxAbundance = 0.00000000067 + Variance = 0 + Dispersal = 1 + } +} + +// Mun Abundance derived from amount of Regolith needed to harvest 1 ton Helium3: 150 million 10 +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 0 + PlanetName = Moon + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.000000000067 + MaxAbundance = 0.000000000067 + Variance = 0 + Dispersal = 1 + } +} + +// Kerbin seafloor is 10 times as abundant in Helium3 as Earth sea floor +BIOME_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 0 + PlanetName = Kerbin + BiomeName = Water + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.0000000000037 + MaxAbundance = 0.0000000001 + Variance = 10 + Dispersal = 10 + } +} + +// Some seafloor sediments on Earth are 2750 times abundant in Helium3 +BIOME_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 0 + PlanetName = Earth + BiomeName = Water + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.00000000000037 + MaxAbundance = 0.00000000001 + Variance = 10 + Dispersal = 10 + } +} + + +//-------------------------- + +//Default : Atmospheric ranges between Kerbin and Jool +GLOBAL_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 2 + + Distribution + { + PresenceChance = 5 + MinAbundance = 0.001 // 0.0000000072 + MaxAbundance = 100 // 0.00014 + Variance = 0 + Dispersal = 1 + } +} + + + +// Kerbin Atmospheric Helium3 abundance is 10 times Earth abundance +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 2 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.001 // 0.00000000072 + MaxAbundance = 0.001 // 0.00000000072 + Variance = 0 + Dispersal = 1 + } +} + + +// PErcentage Helium3 in atmosphere is 1 / 7.2 trillion +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 2 + PlanetName = Earth + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.001 // 0.000000000072 + MaxAbundance = 0.001 // 0.000000000072 + Variance = 0 + Dispersal = 1 + } +} + +// Jool Helium3 abundance is 10 times Jupiter abundance +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 2 + PlanetName = Jool + + Distribution + { + PresenceChance = 100 + MinAbundance = 10 // 0.00014 + MaxAbundance = 10 // 0.00014 + Variance = 0 + Dispersal = 1 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = LqdHe3 + ResourceType = 2 + PlanetName = Jupiter + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 // 0.000014 + MaxAbundance = 1 // 0.000014 + Variance = 0 + Dispersal = 1 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdHydrogen.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdHydrogen.cfg new file mode 100644 index 0000000..e7a1981 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/LqdHydrogen.cfg @@ -0,0 +1,105 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + + +// GLOBAL EXO +GLOBAL_RESOURCE +{ + ResourceName = LqdHydrogen + ResourceType = 3 + + Distribution + { + PresenceChance = 50 + MinAbundance = 1 // .00000001 - Relative atmospheric scaling applied + MaxAbundance = 100 // .00000005 - Relative atmospheric scaling applied + MinAltitude = 500 + MaxAltitude = 200000000000 + MinRange = .01 + MaxRange = .5 + Variance = 20 + } +} + +// SUN EXO +PLANETARY_RESOURCE +{ + ResourceName = LqdHydrogen + ResourceType = 3 + PlanetName = Sun + + Distribution + { + PresenceChance = 100 + MinAbundance = 10 // .00000001 - Relative atmospheric scaling applied + MaxAbundance = 20 // .00000005 - Relative atmospheric scaling applied + MinAltitude = 0.1 + MaxAltitude = 500 + MinRange = 500 + MaxRange = 500 + Variance = 0 + } +} +// JOOL EXO +PLANETARY_RESOURCE +{ + ResourceName = LqdHydrogen + ResourceType = 3 + PlanetName = Jool + Distribution + { + PresenceChance = 100 + MinAbundance = 20 + MaxAbundance = 60 + MinAltitude = 0.1 + MaxAltitude = 0.1 + MinRange = 75 + MaxRange = 100 + Variance = 0 + } +} +// KERBIN EXO +PLANETARY_RESOURCE +{ + ResourceName = LqdHydrogen + ResourceType = 3 + PlanetName = Kerbin + Distribution + { + PresenceChance = 100 + MinAbundance = 40 + MaxAbundance = 80 + MinAltitude = 0.1 + MaxAltitude = 25 + MinRange = 25 + MaxRange = 25 + Variance = 0 + } +} + + +// JOOL ATMO +PLANETARY_RESOURCE +{ + ResourceName = LqdHydrogen + ResourceType = 2 + PlanetName = Jool + + Distribution + { + PresenceChance = 100 + MinAbundance = 62 // 50 - Relative atmospheric scaling applied + MaxAbundance = 100 // 80 - Relative atmospheric scaling applied + Variance = 20 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/MetallicOre.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/MetallicOre.cfg new file mode 100644 index 0000000..5725554 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/MetallicOre.cfg @@ -0,0 +1,58 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +PLANETARY_RESOURCE +{ + ResourceName = MetallicOre + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = MetallicOre + ResourceType = 0 + + Distribution + { + PresenceChance = 70 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = MetallicOre + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Minerals.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Minerals.cfg new file mode 100644 index 0000000..1410a2c --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Minerals.cfg @@ -0,0 +1,58 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +PLANETARY_RESOURCE +{ + ResourceName = Minerals + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Minerals + ResourceType = 0 + + Distribution + { + PresenceChance = 70 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Minerals + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Monazite.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Monazite.cfg new file mode 100644 index 0000000..b3e0bf7 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Monazite.cfg @@ -0,0 +1,59 @@ +// +// Community Resource Pack +// Resource: Monazite +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +PLANETARY_RESOURCE +{ + ResourceName = Monazite + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Monazite + ResourceType = 0 + + Distribution + { + PresenceChance = 80 + MinAbundance = .004 + MaxAbundance = 20 + Variance = 50 + Dispersal = 3 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = Monazite + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .004 + MaxAbundance = 40 + Variance = 50 + Dispersal = 3 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Oxygen.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Oxygen.cfg new file mode 100644 index 0000000..99eaa31 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Oxygen.cfg @@ -0,0 +1,40 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +PLANETARY_RESOURCE +{ + ResourceName = Oxygen + ResourceType = 2 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 65 // 20 - Relative atmospheric scaling applied + MaxAbundance = 100 // 30 - Relative atmospheric scaling applied + Variance = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Oxygen + ResourceType = 2 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 65 // 20 - Relative atmospheric scaling applied + MaxAbundance = 100 // 30 - Relative atmospheric scaling applied + Variance = 0 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/RareMetals.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/RareMetals.cfg new file mode 100644 index 0000000..c83efde --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/RareMetals.cfg @@ -0,0 +1,42 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +PLANETARY_RESOURCE +{ + ResourceName = RareMetals + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = RareMetals + ResourceType = 0 + + Distribution + { + PresenceChance = 50 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 10 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Regolith.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Regolith.cfg new file mode 100644 index 0000000..8a0a78b --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Regolith.cfg @@ -0,0 +1,371 @@ +// +// +// Resource: Regolith (Solar Wind Enriched Regolith) +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +// ####################### Bodys with NO Regolith (Sun, Jool, Laythe) +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Sun + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Jool + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Laythe + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +// ####################### Global definition of Regolith +GLOBAL_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + Distribution + { + PresenceChance = 90 + MinAbundance = 1 + MaxAbundance = 20 + Variance = 50 + Dispersal = 3 + } +} +// ####################### Planetary definition of Regolith +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Moho + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Eve + Distribution + { + PresenceChance = 100 + MinAbundance = 2 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Gilly + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 8 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Kerbin + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 1 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Mun + Distribution + { + PresenceChance = 100 + MinAbundance = 10 + MaxAbundance = 50 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Minmus; See Biome definition. +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Duna + Distribution + { + PresenceChance = 100 + MinAbundance = 2 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Ike + Distribution + { + PresenceChance = 100 + MinAbundance = 10 + MaxAbundance = 50 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Dres + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 8 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Jool here (GasGiant); Regolith prevented, see top. +// No Planetary definition for Laythe here; Regolith prevented, see top. +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Tylo + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 25 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Vall; See Biome definition. +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Bop + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Pol + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Eeloo; See Biome definition. +// ####################### Biome definition of Regolith +// ##### Moho +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Moho + BiomeName = Northern Sinkhole Ridge + Distribution + { + PresenceChance = 100 + MinAbundance = 10 + MaxAbundance = 25 + Variance = 50 + Dispersal = 3 + } +} + +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Moho + BiomeName = Northern Sinkhole + + Distribution + { + PresenceChance = 100 + MinAbundance = 25 + MaxAbundance = 45 + Variance = 50 + Dispersal = 3 + } +} +// ##### Minmus +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Minmus + BiomeName = Poles + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Minmus + BiomeName = Highlands + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Minmus + BiomeName = Midlands + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Minmus + BiomeName = Lowlands + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Minmus + BiomeName = Slopes + Distribution + { + PresenceChance = 100 + MinAbundance = 0.01 + MaxAbundance = 5 + Variance = 50 + Dispersal = 3 + } +} +// ##### Vall +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Vall + BiomeName = Mountains + Distribution + { + PresenceChance = 100 + MinAbundance = 0.5 + MaxAbundance = 4 + Variance = 50 + Dispersal = 3 + } +} +// ##### Eeloo +BIOME_RESOURCE +{ + ResourceName = Regolith + ResourceType = 0 + PlanetName = Eeloo + BiomeName = Ice Canyons + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 9 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Silicates.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Silicates.cfg new file mode 100644 index 0000000..b337d3a --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Silicates.cfg @@ -0,0 +1,336 @@ +// +// Community Resource Pack +// Resource: Silicates +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +// ####################### Bodys with NO Silicates (Sun, Jool, Vall) +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Sun + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE // See Biome definitions +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Minmus + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Jool + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Vall + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +// ####################### Global definition of Silicates +GLOBAL_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + Distribution + { + PresenceChance = 80 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +// ####################### Planetary definition of Silicates +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Moho + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Eve + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 20 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Gilly + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 8 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Kerbin + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Mun + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 25 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Minmus; See Biome definition. +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Duna + Distribution + { + PresenceChance = 100 + MinAbundance = 2 + MaxAbundance = 12 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Ike + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 25 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Dres + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 8 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Jool here (GasGiant); Silicates prevented, see top. +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 10 + MaxAbundance = 30 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Tylo + + Distribution + { + PresenceChance = 100 + MinAbundance = 6 + MaxAbundance = 18 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Vall; Silicates prevented, see top. +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Bop + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 5 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Pol + + Distribution + { + PresenceChance = 100 + MinAbundance = 20 + MaxAbundance = 40 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Eeloo + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.2 + MaxAbundance = 8 + Variance = 50 + Dispersal = 3 + } +} +// ####################### Biome definition of Silicates +// ##### Minmus. All blue areas. +BIOME_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Minmus + BiomeName = Flats + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 7 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Minmus + BiomeName = Lesser Flats + Distribution + { + PresenceChance = 100 + MinAbundance = 2 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Minmus + BiomeName = Great Flats + Distribution + { + PresenceChance = 100 + MinAbundance = 2 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Silicates + ResourceType = 0 + PlanetName = Minmus + BiomeName = Greater Flats + Distribution + { + PresenceChance = 100 + MinAbundance = 2 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Spodumene.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Spodumene.cfg new file mode 100644 index 0000000..6b35e5a --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Spodumene.cfg @@ -0,0 +1,310 @@ +// +// Community Resource Pack +// Resource: Spodumene +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +// ####################### Bodys with NO Spodumene (Sun, Jool) +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Sun + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE // See Biome definitions +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Minmus + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Jool + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} +// ####################### Global definition of Spodumene +GLOBAL_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + Distribution + { + PresenceChance = 80 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +// ####################### Planetary definition of Spodumene +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Moho + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Eve + Distribution + { + PresenceChance = 100 + MinAbundance = 3 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Gilly + Distribution + { + PresenceChance = 100 + MinAbundance = 0.5 + MaxAbundance = 6 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Kerbin + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 20 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Mun + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 20 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Minmus; See Biome definition. +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Duna + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Ike + Distribution + { + PresenceChance = 100 + MinAbundance = 7 + MaxAbundance = 25 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Dres + Distribution + { + PresenceChance = 100 + MinAbundance = 0.5 + MaxAbundance = 7 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Jool here (GasGiant); Spodumene prevented, see top. +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 2 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Tylo + + Distribution + { + PresenceChance = 100 + MinAbundance = 3 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Vall; See Biome definition. +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Bop + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 5 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Pol + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 5 + Variance = 50 + Dispersal = 3 + } +} +// No Planetary definition for Eeloo; See Biome definition. +// ####################### Biome definition of Spodumene +// ##### Minmus +BIOME_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Minmus + BiomeName = Slopes + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 8 + Variance = 50 + Dispersal = 3 + } +} +BIOME_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Minmus + BiomeName = Poles + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 4 + Variance = 50 + Dispersal = 3 + } +} +// ##### Vall +BIOME_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Vall + BiomeName = Mountains + Distribution + { + PresenceChance = 100 + MinAbundance = 0.1 + MaxAbundance = 2 + Variance = 50 + Dispersal = 3 + } +} +// ##### Eeloo +BIOME_RESOURCE +{ + ResourceName = Spodumene + ResourceType = 0 + PlanetName = Eeloo + BiomeName = Ice Canyons + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 15 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Substrate.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Substrate.cfg new file mode 100644 index 0000000..a899ad6 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Substrate.cfg @@ -0,0 +1,59 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +PLANETARY_RESOURCE +{ + ResourceName = Substrate + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Substrate + ResourceType = 0 + + Distribution + { + PresenceChance = 70 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Substrate + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} + diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Uraninite.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Uraninite.cfg new file mode 100644 index 0000000..30b6ba0 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Uraninite.cfg @@ -0,0 +1,58 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// + +PLANETARY_RESOURCE +{ + ResourceName = Uraninite + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Uraninite + ResourceType = 0 + + Distribution + { + PresenceChance = 70 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Uraninite + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Water.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Water.cfg new file mode 100644 index 0000000..b37d0dc --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/Water.cfg @@ -0,0 +1,194 @@ +// +// Community Resource Pack +// Resource: +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.0-100.0, not 0.0-1.0! +// +PLANETARY_RESOURCE +{ + ResourceName = Water + ResourceType = 0 + PlanetName = Jool + + Distribution + { + PresenceChance = 0 + MinAbundance = 0 + MaxAbundance = 0 + Variance = 0 + Dispersal = 0 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Water + ResourceType = 0 + + Distribution + { + PresenceChance = 20 + MinAbundance = .001 + MaxAbundance = 10 + Variance = 50 + Dispersal = 3 + } +} +GLOBAL_RESOURCE +{ + ResourceName = Water + ResourceType = 1 + + Distribution + { + PresenceChance = 20 + MinAbundance = .1 + MaxAbundance = 50 + Variance = 20 + Dispersal = 3 + } +} +GLOBAL_RESOURCE +{ + ResourceName = Water + ResourceType = 2 + + Distribution + { + PresenceChance = 20 + MinAbundance = .1 + MaxAbundance = 50 + Variance = 20 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Water + ResourceType = 0 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 50 + Variance = 20 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Water + ResourceType = 0 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 50 + Variance = 20 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Water + ResourceType = 1 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 90 + MaxAbundance = 90 + Variance = 0 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Water + ResourceType = 2 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 20 + Variance = 10 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Water + ResourceType = 1 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 10 + MaxAbundance = 90 + Variance = 0 + Dispersal = 3 + } +} +PLANETARY_RESOURCE +{ + ResourceName = Water + ResourceType = 2 + PlanetName = Laythe + + Distribution + { + PresenceChance = 100 + MinAbundance = 1 + MaxAbundance = 20 + Variance = 10 + Dispersal = 3 + } +} + +BIOME_RESOURCE +{ + ResourceName = Water + ResourceType = 0 + PlanetName = Duna + BiomeName = Poles + + Distribution + { + PresenceChance = 100 + MinAbundance = 5 + MaxAbundance = 20 + Variance = 10 + Dispersal = 3 + } +} + +GLOBAL_RESOURCE +{ + ResourceName = Water + ResourceType = 3 + + Distribution + { + PresenceChance = 20 + MinAbundance = .001 + MaxAbundance = .5 + MinAltitude = .2 + MaxAltitude = 2 + MinRange = .01 + MaxRange = .5 + } +} \ No newline at end of file diff --git a/Distribution/GameData/CommunityResourcePack/ResourceConfigs/XenonGas.cfg b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/XenonGas.cfg new file mode 100644 index 0000000..a90111e --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/ResourceConfigs/XenonGas.cfg @@ -0,0 +1,94 @@ +// +// Community Resource Pack +// Resource: XenonGas +// +//Resource types: +// 0 = Crustal (Stuff you dig up) +// 1 = Oceanic (Stuff in the oceans) +// 2 = Atmospheric (Stuff in the air, varies with pressure) +// 3 = Interplanetary (Stuff you find between planets) +// +//Express all numbers as percentages 0.001-100.0, not < 0.001 or > 100 +// +// scaled_value =IF(original_value >=1, original_value, ROUND(original_value^0.25, 3)) +// +GLOBAL_RESOURCE +{ + ResourceName = XenonGas + ResourceType = 2 + + Distribution + { + PresenceChance = 50 + MinAbundance = 0.001 // 0.00000005 - Relative atmospheric scaling applied + MaxAbundance = 0.01 // 0.0000005 - Relative atmospheric scaling applied + Variance = 5 + } +} + +// Xenon can be present in Basalt on sea floor +BIOME_RESOURCE +{ + ResourceName = XenonGas + ResourceType = 0 + PlanetName = Kerbin + BiomeName = Water + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.001 + MaxAbundance = 0.01 + Variance = 10 + Dispersal = 3 + } +} + +BIOME_RESOURCE +{ + ResourceName = XenonGas + ResourceType = 0 + PlanetName = Kerbin + BiomeName = Water + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.001 + MaxAbundance = 0.01 + Variance = 10 + Dispersal = 3 + } +} + +BIOME_RESOURCE +{ + ResourceName = XenonGas + ResourceType = 0 + PlanetName = Laythe + BiomeName = Crater Bay + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.01 + MaxAbundance = 0.02 + Variance = 10 + Dispersal = 3 + } +} + +PLANETARY_RESOURCE +{ + ResourceName = XenonGas + ResourceType = 2 + PlanetName = Kerbin + + Distribution + { + PresenceChance = 100 + MinAbundance = 0.001 // 0.00000009 - Relative atmospheric scaling applied + MaxAbundance = 0.002 // 0.0000002 - Relative atmospheric scaling applied + Variance = 5 + } +} diff --git a/Distribution/GameData/CommunityResourcePack/SurfaceScanner.cfg b/Distribution/GameData/CommunityResourcePack/SurfaceScanner.cfg new file mode 100644 index 0000000..c3a7de0 --- /dev/null +++ b/Distribution/GameData/CommunityResourcePack/SurfaceScanner.cfg @@ -0,0 +1,125 @@ +@PART[SurfaceScanner] +{ + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Alumina + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Dirt + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = ExoticMinerals + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Gypsum + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Hydrates + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Karbonite + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = MetallicOre + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Minerals + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = RareMetals + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Regolith + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Silicates + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Spodumene + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Substrate + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Uraninite + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + MODULE + { + name = ModuleResourceScanner + ScannerType = 0 + ResourceName = Water + MaxAbundanceAltitude = 1000 + RequiresUnlock = false + } + + +} \ No newline at end of file diff --git a/Distribution/GameData/README.md b/Distribution/GameData/README.md new file mode 100644 index 0000000..4e1f154 --- /dev/null +++ b/Distribution/GameData/README.md @@ -0,0 +1,32 @@ +ModuleManager +============= + + +Original (c) from Ialdabaoth ( https://github.com/Ialdabaoth ) + +Modified by // Modifications by // Maintained by sarbian ( https://github.com/sarbian ) + + +The original licence requirement was: + +--- + +under a CC share-alike license. Anyone is free to do anything they like with ModuleManager's source, with two caveats: + +1. You credit me as the original creator that your code is based on +2. You make it ABSOLUTELY CLEAR that your code is not the original ModuleManager, and that any problems that people have with your fork should be taken up with YOU, not me. + +--- + + +THIS IS NOT THE ORIGINAL MODULEMANAGER CODE. + +Do not bother Ialdabaoth about any problems with it. + +## Dependencies + +- mono resgen2 + - Fedora: `sudo dnf install mono-devel` +- Mono C# Compiler + - Fedora: `sudo ln -s /usr/bin/mcs /usr/bin/gmcs` + diff --git a/Distribution/GameData/REPOSoftTech/Agencies/Agents.cfg b/Distribution/GameData/REPOSoftTech/Agencies/Agents.cfg new file mode 100644 index 0000000..4de7a39 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/Agencies/Agents.cfg @@ -0,0 +1,14 @@ +AGENT +{ + name = REPOSoftTech + title = #autoLOC_JPLREPO_0001 //REPOSoftTech + description = #autoLOC_JPLREPO_0002 //Experts in the field of cryogenics, ergonomics and electrical equipment, the kerbals at REPOSoftTech are trying hard to keep all space fairing kerbals alive and their missions successful. + + logoURL = REPOSoftTech/Agencies/REPOSoftTech + logoScaledURL = REPOSoftTech/Agencies/REPOSoftTech_scaled + + mentality = Scientific + mentality = Pioneer + mentality = Commercial 0.6 + mentality = Stern 0.25 +} \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/Agencies/REPOSoftTech.png b/Distribution/GameData/REPOSoftTech/Agencies/REPOSoftTech.png new file mode 100644 index 0000000..d9d5c77 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/Agencies/REPOSoftTech.png differ diff --git a/Distribution/GameData/REPOSoftTech/Agencies/REPOSoftTech_scaled.truecolor b/Distribution/GameData/REPOSoftTech/Agencies/REPOSoftTech_scaled.truecolor new file mode 100644 index 0000000..27c9b63 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/Agencies/REPOSoftTech_scaled.truecolor differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300Freezer.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300Freezer.mu new file mode 100644 index 0000000..91aba0a Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300Freezer.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300RFreezer.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300RFreezer.mu new file mode 100644 index 0000000..0942d27 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300RFreezer.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300ROverlay.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300ROverlay.mu new file mode 100644 index 0000000..8987a23 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY-0300ROverlay.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY0300_bump.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY0300_bump.dds new file mode 100644 index 0000000..9e070db Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY0300_bump.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY0300_color.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY0300_color.dds new file mode 100644 index 0000000..b70db05 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY0300_color.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_bump.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_bump.dds new file mode 100644 index 0000000..a745626 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_bump.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_color.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_color.dds new file mode 100644 index 0000000..33c9779 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_color.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-0300Internals.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-0300Internals.mu new file mode 100644 index 0000000..8854284 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-0300Internals.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-0300RInternals.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-0300RInternals.mu new file mode 100644 index 0000000..35ec5cd Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-0300RInternals.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-1300Freezer.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-1300Freezer.mu new file mode 100644 index 0000000..f2a4433 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-1300Freezer.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-1300Internals.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-1300Internals.mu new file mode 100644 index 0000000..f0d4909 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-1300Internals.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-2300Internals.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-2300Internals.mu new file mode 100644 index 0000000..51f00af Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/Cry-2300Internals.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CryopodCushionColor.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CryopodCushionColor.dds new file mode 100644 index 0000000..568fac2 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CryopodCushionColor.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CryopodTexture.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CryopodTexture.dds new file mode 100644 index 0000000..f42c171 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/CryopodTexture.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/GlykerolRadialTank.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/GlykerolRadialTank.mu new file mode 100644 index 0000000..dc0a731 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/GlykerolRadialTank.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/GlykerolTank_diff.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/GlykerolTank_diff.dds new file mode 100644 index 0000000..cdf4e84 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/GlykerolTank_diff.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/RadialCryopodTexture.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/RadialCryopodTexture.dds new file mode 100644 index 0000000..36c48bc Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/RadialCryopodTexture.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/cornerBump.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/cornerBump.dds new file mode 100644 index 0000000..e17207b Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/cornerBump.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/cornerColor.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/cornerColor.dds new file mode 100644 index 0000000..c1c70ac Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/cornerColor.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/hitchhikerIVAcolor.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/hitchhikerIVAcolor.dds new file mode 100644 index 0000000..7d88fc7 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/hitchhikerIVAcolor.dds differ diff --git a/DeepFreeze/Parts/CryoFreezer/model.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model.mu similarity index 99% rename from DeepFreeze/Parts/CryoFreezer/model.mu rename to Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model.mu index aa9c6bd..23ea3cd 100644 Binary files a/DeepFreeze/Parts/CryoFreezer/model.mu and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model000.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model000.dds new file mode 100644 index 0000000..7777fb9 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model000.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model001_NRM.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model001_NRM.dds new file mode 100644 index 0000000..c030437 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/model001_NRM.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/tubesBump.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/tubesBump.dds new file mode 100644 index 0000000..81ca2bd Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/tubesBump.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/tubesColor.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/tubesColor.dds new file mode 100644 index 0000000..5d24354 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/tubesColor.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/wallTextureBump.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/wallTextureBump.dds new file mode 100644 index 0000000..1fa509d Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/wallTextureBump.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/wallTextureColor.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/wallTextureColor.dds new file mode 100644 index 0000000..a62f178 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Assets/wallTextureColor.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Changelog.txt b/Distribution/GameData/REPOSoftTech/DeepFreeze/Changelog.txt new file mode 100644 index 0000000..9c8b6e1 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Changelog.txt @@ -0,0 +1,358 @@ +V0.31.0.0 +Re-Compile for KSP 1.12.x +Added difficulty settings to turn off internal beep sounds and all sounds. +Fix background resources - Kopernicus solar panels integration. +Fix Portraits showing from kerbals in loaded vessels that aren't the active vessel. +Fix timing issue with the Cryopod door animation and freeze glass animation playing at the same time. They now play one after another as they used to/should. +V0.30.0.0 +Re-Compile for KSP 1.11.x +Add EVA construction capabilities to the CRY-300R (Can move it only, can't put in inventories) and the RS-X20R Glykerol Container (can be put in inventories as well). +V0.29.0.0 +Re-Compile for KSP 1.10.x +V0.28.0.0 +Re-Compile for KSP 1.9.x +Fixed the visibility of the CRY-0300 External Door with JSI Advanced Transparent Pods also installed. +Fixed the animated Croypod glass on the CRY-300R. +Added check and screen message when trying to thaw or freeze across multiple parts/vessels at the same time. Already had this check on the same part, but extended across all parts or bad things happen. +More performance and garbage improvements. +Kerbals in Cryopods that have external doors (CRY-0300) will leave their helmet off if the doors are open and in breathable atmosphere. +Russian translations updated by Sooll3. +Chinese translations updated by 6DYZBX. +V0.27.0.0 +Fix dependency issue for Unloaded Resources processing requiring TAC-LS to be installed. +Re-Compile for KSP 1.8.x +V0.26.0.0 +Re-compile for KSP 1.7.2 and above. +Added BackgroundResources processing. This is a module also distributed with my TAC LS mod. It will do EC processing for DeepFreezer parts that +are on unloaded vessels (not the active vessel). You can turn it off in the Difficulty settings. It also does unloaded EC production for all vessels. +V0.25.0.0 +Fix shaders for real this time. - KSP no longer distributes Legacy Shader Transparent Specular. +Some Performance improvements and Garbage generation improvements on the part module. +V0.24.0.0 +Re-compile for KSP 1.6.x +Fix shader assignments. +Fix animations in Cryopods. +V0.23.9.0 +Re-compile for KSP 1.5.x +Added German Translation (thanks Nils277) +Some GC/performance improvements. +Updated CRP to v0.10. +V0.23.8.0 +Re-compile for KSP 1.4.1 +V0.23.7.0 +Re-compile for KSP 1.3.1 +V0.23.6.0 +Russian Localization texts added - Thanks go to forum user- Artem Kerman. +Spanish Localization texts added - Thanks go to forum user- Fitiales. +Resized UI elements to fit other languages. +V0.23.5.0 +Compile for KSP 1.3.0 +Localization ready (but all in English) - Translation volunteers welcome. ;) +If Infinite EC is turned on DeepFreeze will not consume EC. +If in IVA/Internal camera view when you freeze the last kerbal will autmatically change the camera to flight view to avoid invalid camera reference. +V0.23.4.0 +Fix issue with launching vessels with DeepFreeze parts with greater capacity than previously launched vessels would cause +null reference exceptions, lost DeepFreeze tracking and lost frozen kerbals. Thanks to Gnurfos who found the bug. +V0.23.3.0 +Fix Kerbalism Integration. +Freeze Tourists! +DeepFreeze stock application button is not shown in flight unless the active vessel has a DeepFreezer part. +Fixed log spam when RPM occlusion fails. +Work-around for integration issue/bug in USI LS. +V0.23.2.0 +Compile for KSP 1.2.2 +Remove need for RSTKSPEvents and utilize new KSP 1.2.2 GameEvents extension. +Update Community Resource Pack to 0.6.3.0. +Fix Issue when returning to vessel and EC usage has exhausted all EC in the vessel (and not using BackgroundProcessing mod). +V0.23.1.0 +Compile for KSP 1.2.1 +Fix Editor customer Filter for DeepFreeze parts. +Fix problem with EC and Heat settings being disabled in new game difficulty settings. https://github.com/JPLRepo/DeepFreeze/issues/63 +Fix problem with CRY-0300 Doors opening/closing with JSI Advanced Transparent Pods showing an empty Internal until fully open, unfortunately +it does mean you can no longer see the doors animate open/closed correctly. This is a limitation of the JSI Advanced Transparent Pods and camera setup for KSP. +Performance improvement pass on the code. +Fixed Difficulty Settings. +Fixed incorrect use of Blizzy ToolBar on game startup even if user has set to use Stock Icon in difficulty settings. +Implemented inter-mod GameEvents - better integration possible with other mods. +Fixed bug when Comatose Kerbal dies. +Fixed Vessel Switching to unloaded vessel when Low EC or overheat warning occurs. +Removed CRY-0300 door sound when JSI Advanced Transparent Pods mod shuts the door (not the user). +V0.23.0.0 +Update for KSP 1.2 +Fix Coma Kerbals to register/unregister their traits at the correct time and handle Tourist kerbals. +Added Setting in the menu that allows you to turn on/off the VAB/SPH Deepfreeze Parts Category Icon. +Converted all Settings to new Stock Difficulty/Settings Integration. DeepFreeze Settings are now set in the Difficulty window (stock) when starting a new game +and other settings can be changed in-game by bringing up the Settings Menu in-game ane selecting the Difficulty settings button at the top of the window. +Changed the mass of the CRY-0300 from 2,5t to 1.5t to align with other parts. +Added a Database check for orphaned Kerbal and Freezer Part Entries and cleanup on startup. +Fixed config error in texture. +Changed DF VAB/SPH editor filter if ON DeepFreeze parts will only show in the DF category and NOT show in the Utilities category. +V0.22.3.0 +Fix Bug where KAC Alarms GUI window fails if there is a KAC alarm of type "Crew" +Adjustments to internal code for 1.1.3 API changes for Crew Transfers. +Removed Glykerol Defintion from DeepFreeze distribution. Glykerol will now be defined as part of the Community Resource Pack (CRP) V0.5.4.0 and up. +So DeepFreeze is now dependent on CRP and includes CRP in it's distribution. +V0.22.2.0 "Bug Fixes" +Fixed bug with Icons not loading on Linux. +Efficiency clean-up on code modules (speed and memory use). +Fix bug where DeepFreeze is not maintaining and updating Vessel Information for Vessels with Freezer parts, causing Exceptions in the log and vessels not +appearing in the Vessel List in the DeepFreeze GUI window. +Moved Config.cfg file from Plugins to /Plugins/PluginData to prevent resetting Module Manager cache every time you change a setting. +V0.22.1.0 "KSP 1.1.2 Update" +Fixed portrait camera issues. +Fixed On-Screen messages for Kerbal Name when in Alternate - Cryopod Camera mode. +Fixed spacing (scroll lists) in the DeepFreeze GUI menus. +Fixed switching from Stock Toolbar Icon to Blizzy Toolbar Icon and back again. +Made Settings Menu resizable. +Added some more KSPedia pages - What do people want to see here? +V0.22.0.0 "KSP 1.1 Turbo Charged! - Release" +Added first-cut KSPedia Pages - this is really just testing out this feature and is a very rough first cut. Plans to expand and improve this. +Support for NEW RPM - JSIAdvTransparentPods - no longer supports the OLD RPM TJSITransparentPods. You need RPM - JSITransparentPods V0.25.0 or above. +Support for Kerbalism Mod. +Minor Bugs (can live with): +--------------------------- +1) When you freeze/thaw from internal cam (alternate camera) the camera loses the transform reference point at the end of the process. +2) When inside the CRY-0300 with the External Doors closed, if you zoom out strange camera effects mean the door is only partially visible. +3) The screen messages when in Cryopod-Camera mode are not showing all the kerbal's names. +4) When you change settings from Stock to Toolbar and change scenes, the toolbar appears, but stock button is still there. A restart or several scene +changes fixes it. +5) When there is a Kerbal on the ladder in front of the CRY-0300 and the doors are open the Internal Overlays the kerbal and blocks them from view. +This is actually an RPM - JSIAdvTransparentPods bug. +6) The CRY-0300R has lost it's ability to show cool Window Freeze/Thawing animation effects. +Issues with release: +-------------------- +Background Processing is not available under KSP 1.1. Unless the mod author updates it soon I will look to put my own EC background processing +into DeepFreeze. For now if you are using EC usage the non-Background Processing method still works (it plays catch-up when you swith to the vessel). +There is no version of TAC LS for KSP 1.1 - so it is not currently supported. + +V0.21.0.2 "KSP 1.1 Experimentals build 1196" +V0.21.0.1 "KSP 1.1 First Cut Pre-Release" +Working in KSP 1.1 Experimentals build 1172. +V0.20.4.0 "More Fixes" +Fixed bug when using EC for frozen kerbals is turned ON and BackgroundProcessor is not installed. When you switch back to a vessel after a long period of time and you don't +have enough EC to catch-up on the EC usage DeepFreeze was not correctly consuming 95% of remanining EC and was executing the Kill/Emergency Thaw procedure. +Fixed GUI when EC usage is on where the fields were not spanning the resizable window correctly. +Improved error handling for a spurious bug in Tracking Station that cannot be tracked down. +Removed DFInterface.DLL API. Wrapper API now provided for other Mods to interface to DeepFreeze. +Removed use of SMInterface.DLL API to interface to Ship Manifest. Replaced with Reflection Wrapper class. Requires Ship Manifest V5.0.1.0 or above. +Changed DEFAULT CLS setting for the CRY-0300 and CRY-0300R to be Passable (allowing unrestricted crew transfers), this is due to a known bug in CLS/Ship Manifest mods. +Will change this setting back once Papa_Joe fixes that bug in CLS/SM. +Earlier versions of Ship Manifest no longer supported. +Updated Mini-AVC included to newer version to stop log spam. +Added Community Tech Tree science node definitions (via Module Manager file, requires Module Manager). +Re-Factored a lot of code and utilities (Code Housekeeping). +V0.20.3.0 "bug Fixes" +Fixed bug when thawing some kerbals vessel where vessel reference transform was not set in some cases. +Modified debugging and error messages during thawing to assist easier bug hunting in the future. +V0.20.2.0 "Bug fixes" +Fixed null ref bug when vessels are destroyed. +Fixed null ref bug when KSP vessel list cannot be accessed. +Fixed null ref/NAN bug when revert to editor (from vessel with DeepFreeze part) and launch another vessel. +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. +The CRY-0300R supports RasterPropMonitor transparent pods (yes it's transparent if you have RPM installed). +The CRY-0300R also has an external EVA hatch. The CRY-0300R only weighs 0.87t (the full CRY-0300 weights 2.62t) and appears in the TechTree at spaceExploration (same as the CRY-0300). +This now completes the set of all the originally planned DeepFreeze parts. +MerlinsMaster has re-textured more details into all the Cryopods. +Fixed Pod transparency for the CRY-0300 (and the CRY-0300R) based on RPM transparency setting in flight and also now works in the Editor (VAB/SPH). However, due to the +complications of DeepFreeze parts transparency can either be ON or OFF (RPM AUTO setting is treated as Transparency OFF). +Fixed bug where the External Door Open/Close sound effect was not working for the CRY-0300. +Rationalis(z)ed all the part models and textures into one folder, as a lot of them are shared. This will save some memory. Thanks goes to khr15714n for kicking me into doing this as I have been meaning to for a while. +Due to this however, if you are upgrading from a previous version of DeepFreeze you MUST delete the /GameData/REPOSoftTech/DeepFreeze entirely BEFORE installing this version. If you want to save your DeepFreeze +settings make a backup/copy of /GameData/REPOSoftTech/DeepFreeze/Plugins/Config.cfg file BEFORE deleting your DeepFreeze folder then copy you backup/copy of this file +back into the /GameData/REPOSoftTech/DeepFreeze/Plugins folder once you have upgraded. +[B]V0.19.3.0 "KSP 1.0.5"[/B] +re-compile for KSP 1.0.5. +[B]V0.19.2.0 "Bug fixes & Enhancements"[/B] +Fix distribution to include missing Editor group icon from V0.19.0.0 that somehow got left out of V0.19.1.0. +Fix bug that V0.19.2.0 introduced that was causing invalid seat placements and +Add more robust checking of Seat placements for frozen kerbals to avoid bugs that have been occurring for some users. +Fix seat placement when a freeze/thaw process is aborted. +[B]V0.19.1.0 "Bug fixes & Enhancements"[/B] +Added comatose function for when EC or Heat options are ON and Fatal option is OFF. Now when you run out of EC or overheat with these options set kerbals will be emergency thawed +and become comatose (tourists) for a period of 5 minutes (can be changed in the settings menu). +Fixed bug with new pop-up windows when EC is critical or overheat - this pop-up will now NOT appear if the active vessel is the vessel that has run out of EC or overheat. +[B]V0.19.0.0 "Bug fixes & Enhancements"[/B] +Added Fatal EC/Heat option. If this is ON kerbals will die if EC runs out or it gets too hot (if you are using the EC and Heat options). If this is OFF +the Kerbals will be emergency thawed and become available again, and start consuming LS resources again. (to-do - expand this to perhaps make them unusable for a period of time due to +emergency thaw effects, but not in this version) Default setting (for compatibility) is set to ON. - IE: running out of EC or over-heating will Kill kerbals. +Added pop-up window when EC is critical for vessels that are not the active vessel and you can automatically switch to that vessel. +Added flatline sound effect if kerbals die due to lack of EC or over temperature condition. +Support for Texture Replacer V2.4.10, you MUST have this version (or above) of Texture Replacer installed. Thawed kerbals will no longer lose their customised texture settings. +Support for RasterPropMonitor V0.23.0, you MUST have this version (or above) of RPM installed. +Changed the Editor Icon for DeepFreeze parts category to use Snowflake/Freeze icon instead of EVA Kerbal (stock) icon. +Added Engineer Info report check where there is a DeepFreeze Freezer attached that the vessel has 5 or more units of Glykerol available. + +Fixed Engineer report in editor so that DeepFreeze Freezers are now considered parts that use Glykerol and ElectricCharge. +Fixed bug where ships docking/un-docking with frozen kerbals results in unable to thaw frozen kerbals. +Fixed bug in new Internal Camera system when swapping to other DeepFreeze vessels that are in range the cameras do not move/update to the correct vessel. +Fixed bug if you have multiple vessels in loaded range on initially switching to flight mode on one vessel, if you swap to a DeepFreeze equipped vessel (with DeepFreeze part) and you attempt to thaw a previously frozen +kerbal, the thaw may not work or it will work but the kerbal is not visible on thawing. +Fixed issue where a freeze/thaw is in progress and the player switches vessels. DeepFreeze will now abort any in-progress thaw/freeze in this case. +Fixed NullReference bug in DFIntMemory with the internal cameras function. + +[B]V0.18.2.1 "Bug Fixes & Enhancements"[/B] +Fixed distribution file to include missing DFInterface.dll +[B]V0.18.2.0 "Bug Fixes & Enhancements"[/B] +Fix Radial attachment points for CRY-0300 exclusion zones around the external doors. The CRY-0300 now correctly allows you to attach radial parts to the outside of it except for where the external doors are. +There is a EVA Access point at the bottom of the external doors. If you block this with radial parts your EVA access will be blocked by KSP and you will get the "Hatch Obstructed" mesage. +It is recommended you do not attach parts to the doors or the lower front section of the CRY-0300. +Fix DeepFreeze partmodule to support re-use on non DeepFreeze parts. To use you must add partmodule to a crewable part but you must NOT have an internalmodel defined for that part. +Refer to the WIKI page on how to configure your own parts (WARNING: No support will be provided for parts you have made yourself using this method). +All Cryopods now have windows that freeze and thaw (as was our original intent) so they go transparent when empty or a thawed kerbal is seated, and they +appear frozen when a frozen kerbal is within. +You can now switch to Internal Cameras (same cameras used when in IVA and you freeze/thaw a Kerbal) using Modifier key (Windows this is ALT) and d key. +Switch to the next Cryopod Internal Camera using the 'n' key. Switch to the previous Cryopod Internal Camera using the 'b' key. +Press the 'c' or whatever key you have mapped to camera to switch back to IVA/Flight Camera mode. +You can change the key settings in the \GameData\REPOSoftTech\DeepFreeze\Pluginf\Config.cfg file using a text editor (not available via the in-game settings menu). +internalFrzrCamCode = 100 - this is the decimal ASCII code for the CameraMode Key, the default is 100 which is the 'd' key. +internalNxtFrzrCamCode = 110 - this is decimal ASCII code for the Next Freezer Camera Key, the default is 110 which is the 'n' key. +internalPrvFrzrCamCode = 98 - this is decimal ASCII code for the Previous Freezer Camera Key, the default is 98 which is the 'b' key. +The numeric values are from the standard ASCII key code table http://www.asciitable.com/ +Minor adjustments to the CRY-2300 and CRY-1300 Internal models. +Tweaks to the animations - on vessel load pod window states are set immediately, before it used to run the animation loops. The same for when a freeze or thaw event fails. +The Freeze and Thaw Process have been tweaked: On initiating a Freeze or Thaw process the Pod will first Charge the required EC before executing the freeze or thaw process. +New sound effect for charging the Pod EC on Freeze and Thaw. Monitoring equipment sound effect when in IVA/Internal view mode. + +[B]V0.18.1.0 "Bug Fixes"[/B] +Fix GUI LastTimeUpdated field to stop tracking time when settings are changed to turn off ECreqd/Monitoring option. +Fix GUI Colours for EC monitoring, Temp Monitoring and LastTimeUpdated field. +Fix error accessing Kerbal Alarm Clock entries with invalid vessel id's (alarms not attached to vessels) and reduce log spam. +Fix Error in Texture assignments for models. +Fix error loading/saving cryopod states on part load/save. +Fix CRY-0300 transparency issue for some users. + +[B]V0.18.0.0 "Small Freezer but huge changes" Version[/B] +This Upgrade should not be SAVE game breaking. But as always, backup your Persisent save file before upgrading. +If you are upgrading from a previous version it is recommended on first startup of your save game to switch to each existing vessel that has DeepFreeze Continued... +parts attached for about 5 seconds to allow the mod to make updates to each part and save configuration details. +Please ensure you follow the download and install instructions. If you are using TAC LS you [B]must[/B] re-download and apply my workaround fix DLLs from the link in the OP. +Introducing the new 1 Kerbal DeepFreezer part. 1.25M part. It can hold 10 glykerol and one kerbal. +This part has two unique features. It has External Doors that you can open and close IF and only IF you have RasterPropMonitor 0.22.1 (RPM) mod installed. +If you have RPM installed not only can you open and close the external doors, but the internal IVA space is visible from the outside using RPM's transparentpods +feature. To use this feature you will need to install RasterPropMonitor mod and Module Manager mod (required for RPM and DeepFreeze). +If you do not install these mods the CRY-0300 functions in the same way as the other freezer parts. +Due to the external doors you cannot radially attach parts to the doors themselves. As this part is small (1.25M) it is configured to NOT be passable if you are +also using Connected Living Spaces mod. + +Implemented Background Electric Charge consumption if you have BackgroundProcessing Mod installed. This is ONLY applicable if you have the Consume ElectricCharge +option switched ON in settings. +If you do not have BackgroundProcessing Mod installed, Electric Charge consumption will stop when vessels are not the active vessel, but when you return to them the consumption calculation is made based on how long you were away from the vessel and up to 95% of your EC will be used. This gives you little time to recover and save your kerbals before your EC runs out. You can install BackgroundProcessing from this link: https://kerbalstuff.com/mod/302/BackgroundProcessing +The choice is yours depending on what gameplay experience you want. +Unfortunately I have not implemented background Temperature processing yet as I haven't figured out if this is even possible with an unloaded vessel yet. +It appears that it can't be done, but I can and have been proven wrong on lots of things. :) +KNOWN ISSUE?: BackgroundProcessing seems to only remember & process vessels that you have switched to during the current game session. So if I start up KSP and load my save game +I have to switch to each DeepFreeze vessel once before it will start processing my vessel. It does not persist this information from one game session to another. +I am in dialog with that mod author to see if it can be sorted out. This does not cause a problem it just means it's not ideal. Vessels won't run out of EC or kill your kerbals. +DeepFreeze has it's own rough calculation processing that it does on all unloaded vessels to calculate when it thinks the vessel will run out of EC and updates the +DeepFreeze GUI accordingly. + +If that's not all, DeepFreeze Continued... now includes Kerbal Alarm Clock (KAC) mod integration. If you have KAC installed you can bring up a list of all KAC +alarms attached to the active vessel and assign DeepFreeze Thaw and Freeze events to the alarm. So when the alarm fires in KAC DeepFreeze will automatically +execute whatever Thaw and Freeze commands you have attached to that alarm. This ONLY works once the alarm fires and you switch to the vessel that these events +are attached to (if it isn't already the active vessel). DeepFreeze will remember these commands forever and execute them once you switch to this vessel but keep +reminding you to do so until you do switch to the vessel or you delete the alarm events from within Deepfreeze (not KAC). +If you also have Remote Tech mod installed you can only modify DeepFreeze alarm events if the associated vessel has a valid remote connection or a kerbal in command. +DeepFreeze will however execute your alarms even if the vessel does not have a connection or kerbal in command as they are stored and executed by the on-board +computer. :) + +Fixed internal model/part orientation bug with the CRY-2300 internal showing in the portrait cameras of attached parts that also had crew. +[U]Deprecated the original CRY-2300 Part[/U] (which was inherited from ScottPaladin), and replaced it with a renamed part. +This is in order to rename the part as it is known internally to KSP in or der to align with the new parts. This means that in sandbox mode you will noticed TWO CRY-2300 parts (one of which is marked as Deprecated). Please DO NOT create new vessels using this part and it is recommended that all in-flight vessels using this part complete their missions. The deprecated part will be deleted in coming versions. The deprecated part does not appear in career mode, but it will continue to function for all in-flight vessels using the old part. +For those that have no in-flight vessels with a CRY-2300 part attached you can delete the deprecated part from your install by deleting the file:- +\GameData\REPOSoftTech\DeepFreeze\Parts\Cryo2300Freezer\partDepricated.cfg + +Added DeepFreeze Parts Filter category to filter and show Deepfreeze parts in the VAB/SPH. - There is now an icon to filter and show DeepFreeze Continued... parts. +Added REPOSoftTech Agency configuration and logo/flag. +ReFactored RemoteTech Integration -if you have R/T installed and the vessel has no active connection:- + Kerbal Thaw/Freeze events will not appear in part right-click menu + Thaw/Freeze icons are disabled in the DeepFreeze GUI + You are unable to Modify KAC alarms (but existing alarms will still execute) +KNOWN ISSUE: RemoteTech seems to not report connectivity correctly for vessels so the DeepFreeze GUI is only showing what RemoteTech tells it with regard to connectivity, this is not +a DeepFreeze bug. +REPOSoftTech Agency and flag added. +Minor adjustments to internal model glitches and textures on the CRY-2300 and CRY-1300. +New Cryopod model - moved the Status screen on the pods from the bottom of the pods to the top of the pods, so that they are visible when the pod doors are open or closed (before they were obscured when the doors were open). This is in advance of future update to make these screens actually show real data (currently they are a dummy mocked up screen). +All Internals now have light switches on the walls (requires RPM to be installed). +The CRY-0300 has an Internal Door Handle that will operate the external door from the inside (requires RPM to be installed). +Incorporate Alternate Resource Panel Glykerol icon and specific heat capacity adjustment of Glykerol. - Thanks to KSP forum user Olympic1 for this. +Fixed description for CRY-1300 in Editor. - Thanks to KSP Forum user Olympic1 for this. +Added all missing DeepFreeze information from the Freezer parts context (right-click) menu. +Added partname to the IVA camera mode Kerbal info messages. +Moved KSC DeepFreeze messages to bottom right side of screen as they were always obscured by the Vessel/Crew/Science recovery pop-up. +GUI improvements and information display when EC usage/monitoring and Temperature usage/monitoring are switched on. +Re-balanced part costs and Science nodes. + CRY-0300 can be found in the Space Exploration node for entry cost 8,000 and 4,000 per part. + CRY-1300 remains in Specialized Construction , entry cost remains at 12,400 but part cost increased to 6,000 per part. + CRY-2300 remains in Advanced Metalworks but entry cost is no 16,000 and part cost is now 8,000 per part. + The Radial Glykerol tank reamins in Specialized Constructions but entry cost is now 3,000 and part cost is 500 per part. +The Glykerol Radial Tank now holds 25 units of Glykerol. + +[B]V0.17.1.0 "Medium Freezer" Version[/B] +Introducing the New CRY-1300 3-Kerbal capacity 2.5M Freezer part (hitchhiker sized). +Contains 3 DeepFreeze Cryogenic Cryopods and a Glykerol Tank (capacity 15 Glykerol units)[B]. +[/B]New Part at specialized Construction in TechTree. +Moved Cry-2300 10 kerbal Freezer to advanced Metalworks in TechTree. Re-factored Parts Directories, if upgrading please Delete \GameData\REPOSoftTech\DeepFreeeze +before installing. [B] +V0.17.0.0 "Animated Cryopods" Version[/B] +Finalization of the Large Internal, and set-up for all the up-coming parts (as they will use the same base code and animations). +Yes - Animated Cryopods! See for yourself. When you Freeze or Thaw from external view, you will see the Pod open/close in the portrait cameras. +If you are in IVA/Internal mode when you freeze/thaw the camera will switch to an internal camera viewing the pod of the kerbal you are about to freeze/thaw. +It will then animate open/close of the cryopod. This is in place of kicking you out to flight view and removing/replacing the Cryopod windows (which it was doing in previous version). +Fixed Issue with USI LifeSupport consuming resources on thaw of kerbals. DeepFreeze will detect if USI LS is installed and remove tracking in USI LS for kerbals when they are frozen. (Same Issue as TAC LS, but can fix this one in DeepFreeze without waiting for author of other mod to change). +Fixed attach point for the external Glykerol Tank. +Changed the Cry-2300 Internal Glykerol tank to store 50units of Glykerol (instead of 40). This allows you to Freeze 10 kerbals (the part capacity) ONCE without the need for external tanks. +Converted all textures to DDS format. +[B]V0.16.0.3 Support KSP 1.0.4 +[/B]Added the following fields to the Settings file (settings menu in space center). This is NOT save game breaking if upgrading from 0.16.0.0 and up. +heatamtMonitoringFrznKerbals - this is the amount of heat in Kilowatts generated per herbal to run the monitoring equipment. Is only relevant is xxxx is set to on. +heatamtThawFreezeKerbal - is the amount of heat in Kilowatts generated per second when thawing or freezing a kerbal. Is only relevant if xxx is set to ON.heatamtThawFreezeKerbalDon't forget the new heat system in KSP, the amount of kW of heat is proportionate to the part's thermal mass. +This WILL create an issue for anyone who has been using these features in the previous versions. You may notice the first time you switch to a freezer equiped vessel that previously had EC usage or heat generation switched on that it will instantly use up 95% of your EC. So be prepared. +This change will ensure tracking of the last time checked is correct. The down-side is that due to no EC consumption or heat generation during high timewarp or +when the vessel is not the active vessel that when you return to that vessel a spike in usage will occur. +Future versions to address this by providing monitoring and warning of EC usage and heat generation for all vessels including inactive vessels. +Added Messages in the bottom right corner of the screen when you are IVA mode displaying the current Kerbal's name and Crypod number. +Pick-up new Ship Manifest Interface DLL and corrected bug if transferring crew into a freezer that is full of frozen kerbals. +Fixed Pod Numbers in internal model to be correctly numbered. +[B]V0.16.0.2 Support KSP 1.0.3[/B] +Support for KSP 1.0.3. +Expanded and enhanced API for other mods to use and integrate into DeepFreeze. +If you are also using my work-around TACLS DLLs you must +a) install the current version of TACLS +b) then re-download and install my work-around DLLs [URL="https://github.com/JPLRepo/DeepFreeze/blob/master/TACLSTempFixDLLs.zip"]from here[/URL] +c) click the link and then click "view raw" to download the file. +d) Then unzip the two DLLs into your TACLS directory for KSP 1.0.3 and replace existing files. ' + +[B]V0.16.0.0 Full IVA implemented.[/B] and a few more things, like:- +IVA portrait cameras now correctly update when you thaw and xfer kerbals. Did I mention portrait cameras? Oh wait - IVA Internal texturing now completed for Large Freezer. +All Praise to MerlinsMaster for his Amazing!! Internal modelling and texturing. So now the portrait cameras will correctly display thawed (Crewed?) crew and Frozen crew. In Internal IVA mode you cannot switch the camera to frozen kerbals. They're frozen! and their eyes don't work. You can switch around all the un-frozen kerbals seat cameras to take a look around. If you attempt to freeze a kerbal while in IVA mode the camera will automatically switch back to Flight mode. This is because the Kerbals want privacy while they get frozen. +Snacks! - Vessel Supply screen now correctly updates to reflect number of active crew on-board. +TAC LS - You still have to use my workaround re-build of TAC LS here. +Remote Tech is now supported. +Finally fixed Crew Xfers and seat allocations for frozen kerbals correctly. +Added Temperature Checking function. +Fixed the on-going ElectricCharge function. If you run out of ElectricCharge the freezer systems will go critical. +A countdown timer will commence and when it finishes if you have not restored charge all your frozen Kerbals will DIE!! +Updated the DeepFreeze GUI to include monitoring section for Temperature and EC if you have switched them on in the settings. +Updated GUI to include scrollbars. +Part config file changes (see descriptions above). +Config/Settings file changes (see descriptions above). +Now has a Config/Settings Window at the SpaceCenter that allows you to change the following config file settings from in-game. +To access bring up the Deepfreeze Window at the Space Center by clicking the DeepFreeze App Icon and then click "settings" at the bottom of the window. + +[B]V0.15.0.5 Initial full release[/B] of DeepFreeze Continued... +Changes since Dev version -.14.3 include, [B]but not limited to[/B]:- +New Radial Attached Glykerol tank. Glykerol storage inside the large DeepFreeze part reduced from 100 to 40 units. +New IVA in place, Needs finalization of the model and textures added - next version. +Ship Manifest support (using new interface supplied by Papa_Joe) and crew transfers working correctly (Kerbals not getting shoved into lockers any more). +Added a API for future other mod (such as life support mods) support. +GUI changes and tweaks. - Tracks kerbals per vessel, includes vesselname in GUI. GUI can be resized and dragged, includes close button. +Can now optionally change config file to automatically recover kerbals or not on vessel recovery (at a cost). +Added config file parameters. +Lots more bugs squashed. +Moved the install directory from GameData\PalladinLabs\DeepFreeze to GameData\REPOSoftTech\DeepFreeze \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/DFLocalization.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/DFLocalization.cfg new file mode 100644 index 0000000..5f13c40 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/DFLocalization.cfg @@ -0,0 +1,1332 @@ +Localization +{ + en-us + { + #autoLOC_DF_00001 = <<1>> has recovered from emergency thaw and resumed normal duties. + #autoLOC_DF_00002 = <<1>> has been emergency thawed and cannot perform duties for <<2>> minutes. + #autoLOC_DF_00003 = DeepFreeze + #autoLOC_DF_00004 = DeepFreeze Vessel Switch + #autoLOC_DF_00005 = DeepFreeze Vessel Switch Failed + #autoLOC_DF_00006 = DeepFreeze Kerbals + #autoLOC_DF_00007 = DeepFreeze Alarms + #autoLOC_DF_00008 = Close Window + #autoLOC_DF_00009 = Vessel + #autoLOC_DF_00010 = Vessel Name + #autoLOC_DF_00011 = Part + #autoLOC_DF_00012 = Part Name + #autoLOC_DF_00013 = Tmp + #autoLOC_DF_00014 = Part Temperature Status + #autoLOC_DF_00015 = EC + #autoLOC_DF_00016 = Electric Charge Status + #autoLOC_DF_00017 = R.T + #autoLOC_DF_00018 = Remote Tech Status + #autoLOC_DF_00019 = Alarms + #autoLOC_DF_00020 = Press the button for Kerbal Alarm Clock Alarms assigned to this part + #autoLOC_DF_00021 = LastUpd + #autoLOC_DF_00022 = The Time the part was last updated + #autoLOC_DF_00023 = TimeRem + #autoLOC_DF_00024 = Approx. time remaining before Electric Charge will run out + #autoLOC_DF_00025 = Vessel <<1>> is Over-Heating. + #autoLOC_DF_00026 = OFF + #autoLOC_DF_00027 = S/BY + #autoLOC_DF_00028 = OUT + #autoLOC_DF_00029 = Vesssel <<1>> is out of ElectricCharge.\n Situation Critical. + #autoLOC_DF_00030 = ALRT + #autoLOC_DF_00031 = Vessel <<1>> is almost out of ElectricCharge. + #autoLOC_DF_00032 = LOW + #autoLOC_DF_00033 = OK + #autoLOC_DF_00034 = NC + #autoLOC_DF_00035 = Alarm + #autoLOC_DF_00036 = Go to Alarms + #autoLOC_DF_00037 = There are currently no Frozen Kerbals + #autoLOC_DF_00038 = Kerbal Name + #autoLOC_DF_00039 = Profession + #autoLOC_DF_00040 = Thaw + #autoLOC_DF_00041 = Thaw this kerbal + #autoLOC_DF_00042 = Cannot thaw <<1>> from KSC. Vessel still exists <<2>> at <<3>> + #autoLOC_DF_00043 = Freeze + #autoLOC_DF_00044 = Freeze this kerbal + #autoLOC_DF_00045 = KAC Alarms + #autoLOC_DF_00046 = Resize Window + #autoLOC_DF_00047 = <<1>>K + #autoLOC_DF_00048 = <<2>>C + #autoLOC_DF_00049 = <<1>> was stored frozen at KSC + #autoLOC_DF_00050 = Insufficient funds to thaw <<1>> at this time + #autoLOC_DF_00051 = <<1>> was found and thawed out + #autoLOC_DF_00052 = <<1>> was found and thawed out <<2>> funds deducted from account + #autoLOC_DF_00053 = Cannot thaw <<1>> vessel still exists <<2>> at <<3>> + + #autoLOC_DF_00054 = Freezer Capacity + #autoLOC_DF_00055 = Total Frozen Kerbals + #autoLOC_DF_00056 = Freezer Space + #autoLOC_DF_00057 = Part is Full? + #autoLOC_DF_00058 = R/T Connection + #autoLOC_DF_00059 = Freezer Temp + #autoLOC_DF_00060 = Cabin Temperature + #autoLOC_DF_00061 = K + #autoLOC_DF_00062 = DeepFreeze Menu + #autoLOC_DF_00063 = EC p/Kerbal to run + #autoLOC_DF_00064 = \u0020p/min + #autoLOC_DF_00065 = Current EC Usage + #autoLOC_DF_00066 = \u0020p/sec + #autoLOC_DF_00067 = Glykerol Reqd. to Freeze + #autoLOC_DF_00068 = EC p/Kerbal to Frze/Thaw + #autoLOC_DF_00069 = \nCryopods: <<1>> + #autoLOC_DF_00070 = C + #autoLOC_DF_00071 = Pod:<<1>> + #autoLOC_DF_00072 = Insufficient electric charge to monitor frozen kerbals. + #autoLOC_DF_00073 = \u0020Freezer Out of EC : Systems critical in <<1>> secs + #autoLOC_DF_00074 = <<1>> died due to lack of Electrical Charge to run cryogenics + #autoLOC_DF_00075 = Check Temperatures, Freezer getting hot + #autoLOC_DF_00076 = Warning!! Check Temperatures NOW, Freezer getting very hot + #autoLOC_DF_00077 = Temperature getting too hot for kerbals to remain frozen. + #autoLOC_DF_00078 = Freezer Over Temp : Systems critical in <<1>> secs + #autoLOC_DF_00079 = <<1>> died due to overheating, cannot keep frozen + #autoLOC_DF_00080 = Over Temperature - Emergency Thaw in Progress. + #autoLOC_DF_00081 = Insufficient electric charge to freeze kerbal + #autoLOC_DF_00082 = \u0020Cryopod - Charging: <<1>> + #autoLOC_DF_00083 = Insufficient Glykerol to freeze kerbal + #autoLOC_DF_00084 = Cannot Freeze while Temperature greater than <<1>> + #autoLOC_DF_00085 = Cannot Freeze while Crew Xfer in progress + #autoLOC_DF_00086 = Cannot run Freeze process on more than one Kerbal at a time + #autoLOC_DF_00087 = RemoteTech Detected. Press Freeze Again if you want to Freeze your Last Active Kerbal + #autoLOC_DF_00088 = An Active connection or Active Kerbal is Required On-Board to Initiate Thaw Process + #autoLOC_DF_00089 = Cannot freeze kerbal. Freezer is full + #autoLOC_DF_00090 = Cannot freeze kerbal at this time + #autoLOC_DF_00091 = Starting Freeze process + #autoLOC_DF_00092 = Freezing Aborted + #autoLOC_DF_00093 = <<1>> frozen + #autoLOC_DF_00094 = Insufficient electric charge to thaw kerbal + #autoLOC_DF_00095 = \u0020Cryopod - Charging:<<1>> + #autoLOC_DF_00096 = Cannot Thaw <<1>> Part is full + #autoLOC_DF_00097 = Cannot Thaw while Crew Xfer in progress + #autoLOC_DF_00098 = Cannot run Thaw process on more than one Kerbal at a time + #autoLOC_DF_00099 = Cannot thaw kerbal at this time + #autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + #autoLOC_DF_00101 = Thawing Aborted + #autoLOC_DF_00102 = <<1>> thawed out + #autoLOC_DF_00103 = <<1>> was thawed out due to lack of Electrical Charge to run cryogenics + #autoLOC_DF_00104 = DeepFreezer mechanical failure + #autoLOC_DF_00105 = Vessel about to change, Aborting Thaw process + #autoLOC_DF_00106 = Vessel about to change, Aborting Freeze process + + #autoLOC_DF_00107 = DeepFreeze Items + #autoLOC_DF_00108 = There is less than 5 units of Glykerol on-board for your DeepFreeze Freezers + #autoLOC_DF_00109 = A DeepFreeze Alarm event has occurred. Please Switch to <<1>> to execute. + #autoLOC_DF_00110 = DeepFreeze Alarm processing completed. + + #autoLOC_DF_00111 = Name + #autoLOC_DF_00112 = Alarm Name + #autoLOC_DF_00113 = Alarm Type + #autoLOC_DF_00114 = KAC Alarm Type + #autoLOC_DF_00115 = Time Remain. + #autoLOC_DF_00116 = Time remaining before Alarm is triggered + #autoLOC_DF_00117 = There are currently no KAC alarms associated to a DeepFreeze vessel + #autoLOC_DF_00118 = Delete + #autoLOC_DF_00119 = Delete this KAC alarm completely + #autoLOC_DF_00120 = Modify + #autoLOC_DF_00121 = Modify this Alarm + #autoLOC_DF_00122 = Save + #autoLOC_DF_00123 = Save Alarm Changes + #autoLOC_DF_00124 = Cannot Save Alarm. No R/Tech Connection to vessel. + #autoLOC_DF_00125 = DeepFreeze Alarm changes Saved. + #autoLOC_DF_00126 = DeepFreeze Cannot Save alarm changes, Time is up. + #autoLOC_DF_00127 = Cancel + #autoLOC_DF_00128 = Cancel any changes + #autoLOC_DF_00129 = Name + #autoLOC_DF_00130 = The Kerbals Name + #autoLOC_DF_00131 = Trait + #autoLOC_DF_00132 = The Kerbals Profession + #autoLOC_DF_00133 = Thaw + #autoLOC_DF_00134 = Thaw this kerbal on alarm activation + #autoLOC_DF_00135 = Freeze + #autoLOC_DF_00136 = Freeze this kerbal on alarm activation + #autoLOC_DF_00137 = Modify + #autoLOC_DF_00138 = Modify this Alarms settings + + #autoLOC_DF_00139 = Switch to Vessel + #autoLOC_DF_00140 = Not Now + #autoLOC_DF_00141 = Don't switch vessel now + #autoLOC_DF_00142 = Automatic Switch to vessel failed.\nPlease switch manually to vessel Immediately + #autoLOC_DF_00143 = Switch to DeepFreeze vessel required + + #autoLOC_DF_00144 = DeepFreeze Options + #autoLOC_DF_00145 = ElectricCharge Required to run Freezers + #autoLOC_DF_00146 = If on, EC is required to run freezers + #autoLOC_DF_00147 = Fatal EC/Heat Option + #autoLOC_DF_00148 = If on Kerbals will die if EC runs out or it gets too hot + #autoLOC_DF_00149 = Non Fatal Comatose Time(in secs) + #autoLOC_DF_00150 = The time in seconds a kerbal is comatose\n if fatal EC / Heat option is off + #autoLOC_DF_00151 = AutoRecover Frozen Kerbals at KSC + #autoLOC_DF_00152 = If on, will AutoRecover Frozen Kerbals at the KSC\n and deduct the Cost from your funds + #autoLOC_DF_00153 = Cost to Thaw a Kerbal at KSC + #autoLOC_DF_00154 = Amt of currency Reqd to Freeze a Kerbal from the KSC + #autoLOC_DF_00155 = EC Reqd to Freeze/Thaw a Kerbal + #autoLOC_DF_00156 = Amt of ElecCharge Reqd to Freeze/Thaw a Kerbal. + #autoLOC_DF_00157 = Glykerol Reqd to Freeze a Kerbal + #autoLOC_DF_00158 = Amt of Glykerol used to Freeze a Kerbal,\nOverrides Part values. + #autoLOC_DF_00159 = DeepFreeze Temperatures + #autoLOC_DF_00160 = Get your calculator out. + #autoLOC_DF_00161 = Temps are in (K)elvin. (K) = (C)elcius + 273.15. (K) = ((F)arenheit + 459.67) × 5/9. Get your calculator out + #autoLOC_DF_00162 = Regulated Temperatures Required + #autoLOC_DF_00163 = If on, Regulated Temps apply to freeze\nand keep Kerbals Frozen. + #autoLOC_DF_00164 = Min. Temp. for Freezer to Freeze(K) + #autoLOC_DF_00165 = The minimum temperature (in Kelvin) for a Freezer\nto be able to Freeze a Kerbal. + #autoLOC_DF_00166 = Max. Temp. to keep Kerbals Frozen(K) + #autoLOC_DF_00167 = The maximum temperature (in Kelvin) for a Freezer\nto keep Kerbals frozen. + #autoLOC_DF_00168 = Heat generated per kerbal (kW/min) + #autoLOC_DF_00169 = Amount of thermal heat (kW) generated\nby equipment for each frozen kerbal per minute. + #autoLOC_DF_00170 = Heat generated freezer process(kW) + #autoLOC_DF_00171 = Amount of thermal heat (kW) generated\nwith each thaw/freeze process. + #autoLOC_DF_00172 = Show Part Temperatures in Kelvin + #autoLOC_DF_00173 = If on Part right click will show temp in Kelvin,\nif Off will show in Celcius. + #autoLOC_DF_00174 = DeepFreeze Misc. + #autoLOC_DF_00175 = Freezer Strip Lights On + #autoLOC_DF_00176 = Turn off if you do not want the internal\nfreezer strip lights to function. + #autoLOC_DF_00177 = ToolTips On + #autoLOC_DF_00178 = Turn the Tooltips on and off. + #autoLOC_DF_00179 = Editor Filter + #autoLOC_DF_00180 = Turn the DeepFreeze Editor filter Category on and off. + #autoLOC_DF_00181 = Use Stock App Launcher Icon + #autoLOC_DF_00182 = If on, the Stock Application launcher will be used,\nif off will use Blizzy Toolbar if installed. + #autoLOC_DF_00183 = Extra Debug Logging + #autoLOC_DF_00184 = Turn this On to capture lots of extra information\ninto the KSP log for reporting a problem. + + #autoLOC_DF_00185 = CRY-0300 Cryonic Freezing Chamber + #autoLOC_DF_00186 = REPOSoftTech + #autoLOC_DF_00187 = Designed for long term storage of 1 kerbal. The CRY-0300 uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-0300 comes stocked with 10 units of Glykerol. CAUTION: The CRY-0300 also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00188 = deepfreeze cryogenic freezer + #autoLOC_DF_00189 = CRY-0300R Cryonic Freezing Chamber + #autoLOC_DF_00190 = Designed for long term storage of 1 kerbal. The CRY-0300R uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-0300R comes stocked with 10 units of Glykerol. CAUTION: The CRY-0300R also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00191 = CRY-1300 Cryonic Freezing Chamber + #autoLOC_DF_00192 = Designed for long term storage of up to 3 Kerbals. The CRY-1300 uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-1300 comes stocked with 15 units of Glykerol. CAUTION: The CRY-1300 also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00193 = CRY-2300 Cryonic Freezing Chamber + #autoLOC_DF_00194 = Designed for long term storage of up to 10 Kerbals. The CRY-2300 uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-2300 comes stocked with 50 units of Glykerol. CAUTION: The CRY-2300 also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00195 = RS-X20R Glykerol Container + #autoLOC_DF_00196 = The RS-X20R is a small-volume Radial Glykerol container, for all your Kerbal Freezing and Thawing needs. Brought to you by the good folks at REPOSoftTech. Warranty void if filled with Glykerol. + #autoLOC_DF_00197 = deepfreeze cryogenic freezer glykerol tank + + #autoLOC_DF_00198 = Experts in the field of cryogenics, ergonomics and electrical equipment, the kerbals at REPOSoftTech are trying hard to keep all space fairing kerbals alive and their missions successful. + + #autoLOC_DF_00199 = Freeze <<1>> + #autoLOC_DF_00200 = Thaw <<1>> + + #autoLOC_DF_00201 = Unloaded Vessel Processing + #autoLOC_DF_00202 = If enabled DeepFreeze will process resources on unloaded vessels. If disabled, it won't and play the catchup and estimation game. + #autoLOC_DF_00203 = Beep Sounds On + #autoLOC_DF_00204 = If enabled Beep sounds are heard inside freezer parts with frozen kerbals. + #autoLOC_DF_00205 = Other Sounds On + #autoLOC_DF_00206 = If enabled all other DeepFreeze sounds are heard. + } +} + +Localization +{ + es-es + { + #autoLOC_DF_00001 = <<1>> se ha recuperado del deshielo de emergencia y ha reanudado las tareas normales. + #autoLOC_DF_00002 = <<1>> ha sido descongelado de emergencia y no puede realizar tareas por <<2>> minutos. + #autoLOC_DF_00003 = CongelaciónProfunda + #autoLOC_DF_00004 = Conmutador de nave CongelaciónProfunda + #autoLOC_DF_00005 = Fallo Conmutador de nave CongelaciónProfunda + #autoLOC_DF_00006 = CongelaciónProfunda de Kerbals + #autoLOC_DF_00007 = CongelaciónProfunda de Alarmas + #autoLOC_DF_00008 = Cerrar Ventana + #autoLOC_DF_00009 = Nave + #autoLOC_DF_00010 = Nombre de Nave + #autoLOC_DF_00011 = Parte + #autoLOC_DF_00012 = Nombre de parte + #autoLOC_DF_00013 = Tmp + #autoLOC_DF_00014 = Estado de temperatura de pieza + #autoLOC_DF_00015 = CE + #autoLOC_DF_00016 = Estado de carga eléctrica + #autoLOC_DF_00017 = T.R + #autoLOC_DF_00018 = Estado de Tecnología Remota + #autoLOC_DF_00019 = Alarmas + #autoLOC_DF_00020 = Presione el botón Alarmas de Kerbal Alarm Clock asignadas a esta parte + #autoLOC_DF_00021 = ÚltimaActu + #autoLOC_DF_00022 = Momento en que se actualizó la parte por última vez + #autoLOC_DF_00023 = TiempoRes + #autoLOC_DF_00024 = Aprox. Tiempo restante antes de que la carga eléctrica se agote + #autoLOC_DF_00025 = Nave <<1>> está sobrecalentada. + #autoLOC_DF_00026 = APAGADO + #autoLOC_DF_00027 = MANTÉN + #autoLOC_DF_00028 = FUERA + #autoLOC_DF_00029 = Nave <<1>> está sin carga eléctrica.\n Situación crítica. + #autoLOC_DF_00030 = ALRT + #autoLOC_DF_00031 = Nave <<1>> está casi fuera de carga eléctrica. + #autoLOC_DF_00032 = BAJO + #autoLOC_DF_00033 = OK + #autoLOC_DF_00034 = NC + #autoLOC_DF_00035 = Alarma + #autoLOC_DF_00036 = Ir a Alarmas + #autoLOC_DF_00037 = Actualmente no hay Kerbals congelados + #autoLOC_DF_00038 = Nombre Kerbal + #autoLOC_DF_00039 = Profesión + #autoLOC_DF_00040 = Deshielo + #autoLOC_DF_00041 = Descongele este kerbal + #autoLOC_DF_00042 = No se puede descongelar <<1>> desde KSC. La nave todavía existe <<2>> en <<3>> + #autoLOC_DF_00043 = Congelar + #autoLOC_DF_00044 = Congelar este kerbal + #autoLOC_DF_00045 = Alarmas KAC + #autoLOC_DF_00046 = Cambiar tamaño de ventana + #autoLOC_DF_00047 = <<1>>K + #autoLOC_DF_00048 = <<2>>C + #autoLOC_DF_00049 = <<1>> se almacenó congelado en KSC + #autoLOC_DF_00050 = Fondos insuficientes para descongelar <<1>> en este momento + #autoLOC_DF_00051 = <<1>> fue encontrado y descongelado + #autoLOC_DF_00052 = <<1>> fue encontrado y descongelado <<2>> fondos deducidos de la cuenta + #autoLOC_DF_00053 = No se puede descongelar <<1>> La nave todavía existe <<2>> en <<3>> + + #autoLOC_DF_00054 = Capacidad del Congelador + #autoLOC_DF_00055 = Total de Kerbales congelados + #autoLOC_DF_00056 = Espacio Congelador + #autoLOC_DF_00057 = ¿La parte está llena? + #autoLOC_DF_00058 = Conexión T/R + #autoLOC_DF_00059 = Tempt del congelador + #autoLOC_DF_00060 = Temperatura de cabina + #autoLOC_DF_00061 = K + #autoLOC_DF_00062 = Menu CongelaciónProfunda + #autoLOC_DF_00063 = CE p/Kerbal para funcionar + #autoLOC_DF_00064 = \u0020p/min + #autoLOC_DF_00065 = Uso actual de CE + #autoLOC_DF_00066 = \u0020p/seg + #autoLOC_DF_00067 = Glykerol Requd. para congelar + #autoLOC_DF_00068 = CE p/Kerbal para Congl/Deshelar + #autoLOC_DF_00069 = \nCriocápsulas: <<1>> + #autoLOC_DF_00070 = C + #autoLOC_DF_00071 = Cápsula:<<1>> + #autoLOC_DF_00072 = Carga eléctrica insuficiente para monitorear los kerbales congelados. + #autoLOC_DF_00073 = \u0020Congelador sin CE : Sistemas críticos en <<1>> segs + #autoLOC_DF_00074 = <<1>> murió debido a la falta de carga eléctrica para ejecutar criogenia + #autoLOC_DF_00075 = Comprobar temperaturas, Congelador caliente + #autoLOC_DF_00076 = ¡¡Advertencia!! Revise las temperaturas AHORA, el congelador está muy caliente + #autoLOC_DF_00077 = Temperatura demasiado caliente para que los kerbals permanezcan congelados. + #autoLOC_DF_00078 = Congelador sobre temp : Sistemas críticos en <<1>> segs + #autoLOC_DF_00079 = <<1>> murió debido a sobrecalentamiento, no puede mantener congelado + #autoLOC_DF_00080 = Exceso de temperatura - Descongelación de emergencia en curso. + #autoLOC_DF_00081 = Carga eléctrica insuficiente para congelar kerbal + #autoLOC_DF_00082 = \u0020Criocápsula - Cargando: <<1>> + #autoLOC_DF_00083 = Glykerol insuficiente para congelar kerbal + #autoLOC_DF_00084 = No se puede congelar mientras la temperatura es mayor que <<1>> + #autoLOC_DF_00085 = No se puede congelar mientras hay en curso una transferencia + #autoLOC_DF_00086 = No se puede ejecutar el proceso de congelación en más de un Kerbal a la vez + #autoLOC_DF_00087 = Tencnología Remota detectada. Presione congelar de nuevo si desea congelar su último activo Kerbal + #autoLOC_DF_00088 = Se requiere una conexión activa o Kerbal activo a bordo para iniciar el proceso de descongelación + #autoLOC_DF_00089 = No se puede congelar kerbal. El congelador está lleno + #autoLOC_DF_00090 = No se puede congelar kerbal en este momento + #autoLOC_DF_00091 = Proceso de congelación inicial + #autoLOC_DF_00092 = Congelación Abortada + #autoLOC_DF_00093 = <<1>> congelado + #autoLOC_DF_00094 = Carga eléctrica insuficiente para descongelar kerbal + #autoLOC_DF_00095 = \u0020Criocápsula - Cargando:<<1>> + #autoLOC_DF_00096 = No se puede descongelar <<1>> La parte está llena + #autoLOC_DF_00097 = No se puede congelar mientras hay en curso una transferencia + #autoLOC_DF_00098 = No se puede ejecutar el proceso de descongelación en más de un Kerbal a la vez + #autoLOC_DF_00099 = No se puede descongelar kerbal en este momento + #autoLOC_DF_00100 = Error de código: No se puede descongelar kerbal en este momento, registro de verificación + #autoLOC_DF_00101 = Descongelación interrumpida + #autoLOC_DF_00102 = <<1>> descongelado + #autoLOC_DF_00103 = <<1>> fue descongelado debido a la falta de carga eléctrica para ejecutar criogenia + #autoLOC_DF_00104 = Falla mecánica del congelador + #autoLOC_DF_00105 = La nave está a punto de cambiar, Abortando el proceso de descongelación + #autoLOC_DF_00106 = La nave está a punto de cambiar, Abortando el proceso de congelación + + #autoLOC_DF_00107 = Artículos CongelaciónProfunda + #autoLOC_DF_00108 = Hay menos de 5 unidades de Glykerol a bordo para sus congeladores DeepFreeze + #autoLOC_DF_00109 = Se ha producido un evento de alarma de CongelaciónProfunda. Por favor, cambie a <<1>> para ejecutar. + #autoLOC_DF_00110 = Proceso de alarma CongelaciónProfunda completado. + + #autoLOC_DF_00111 = Nombre + #autoLOC_DF_00112 = Nombre Alarma + #autoLOC_DF_00113 = Tipo Alarma + #autoLOC_DF_00114 = Tipo Alarma KAC + #autoLOC_DF_00115 = Tiempo Restante. + #autoLOC_DF_00116 = Tiempo restante antes de que se active la alarma + #autoLOC_DF_00117 = Actualmente no hay alarmas KAC asociadas a una nave CongelaciónProfunda + #autoLOC_DF_00118 = Borrar + #autoLOC_DF_00119 = Eliminar completamente esta alarma KAC + #autoLOC_DF_00120 = Modificar + #autoLOC_DF_00121 = Modificar esta Alarma + #autoLOC_DF_00122 = Guardar + #autoLOC_DF_00123 = Guardar cambios de alarma + #autoLOC_DF_00124 = No se puede guardar la alarma. No hay conexión R/Tech con la nave. + #autoLOC_DF_00125 = Cambios de alarma CongelaciónProfunda guardados. + #autoLOC_DF_00126 = CongelaciónProfunda no puede guardar los cambios de alarma, el tiempo ha terminado. + #autoLOC_DF_00127 = Cancelar + #autoLOC_DF_00128 = Cancelar cualquier cambio + #autoLOC_DF_00129 = Nombre + #autoLOC_DF_00130 = Nombre de Kerbals + #autoLOC_DF_00131 = Rasgo + #autoLOC_DF_00132 = Profesión de Kerbals + #autoLOC_DF_00133 = Deshelar + #autoLOC_DF_00134 = Descongelar este kerbal en la activación de alarma + #autoLOC_DF_00135 = Congelar + #autoLOC_DF_00136 = Congelar este kerbal en la activación de alarma + #autoLOC_DF_00137 = Modificar + #autoLOC_DF_00138 = Modificar esta configuración de alarmas + + #autoLOC_DF_00139 = Cambiar a nave + #autoLOC_DF_00140 = Ahora no + #autoLOC_DF_00141 = No cambiar de nave ahora + #autoLOC_DF_00142 = El cambio automático a nave falló.\nCambie manualmente a nave Inmediatamente + #autoLOC_DF_00143 = Cambiar a nave CongelaciónProfunda requerida + + #autoLOC_DF_00144 = Opciones CongelaciónProfunda + #autoLOC_DF_00145 = Carga eléctrica requerida para hacer funcionar los congeladores + #autoLOC_DF_00146 = Si está encendido, se requiere CE para funcionar los congeladores + #autoLOC_DF_00147 = Fatal CE/Opción de calor + #autoLOC_DF_00148 = Si está encendido, el Kerbal va a morir Si CE se agota o calienta demasiado + #autoLOC_DF_00149 = Tiempo Comatoso No Fatal(en segs) + #autoLOC_DF_00150 = El tiempo en segundos que kerbal está comatoso\n si CE es fatal / Opción de calor está desactivada + #autoLOC_DF_00151 = Recuperación automática de Kerbals congelados en KSC + #autoLOC_DF_00152 = Si está encendido, Recuperará automáticamente los Kerbals congelados en el KSC\n y deducirá el Costo de sus fondos + #autoLOC_DF_00153 = Costo para descongelar un Kerbal en KSC + #autoLOC_DF_00154 = Cantidad de moneda Reqd para congelar un Kerbal de KSC + #autoLOC_DF_00155 = CE Reqd para congelar/descongelar un Kerbal + #autoLOC_DF_00156 = Cantidad de Carga Eléctrica Reqd para Congelar/Descongelar un Kerbal. + #autoLOC_DF_00157 = Glykerol Reqd para congelar un Kerbal + #autoLOC_DF_00158 = Cantidad de Glykerol usada para congelar un Kerbal,\nAnula valores de parte. + #autoLOC_DF_00159 = Temperaturas CongelaciónProfunda + #autoLOC_DF_00160 = Saca tu calculadora. + #autoLOC_DF_00161 = Las temperaturas están en (K)elvin. (K) = (C)elcius + 273.15. (K) = ((F)arenheit + 459.67) × 5/9. Saca tu calculadora + #autoLOC_DF_00162 = Temperaturas reguladas requeridas + #autoLOC_DF_00163 = Si está encendido, Temperaturas reguladas se aplican para congelar\ny mantener Kerbal congelado. + #autoLOC_DF_00164 = Min. Temperatura. Congelador para congelar(K) + #autoLOC_DF_00165 = La temperatura mínima (en Kelvin) para un congelador\nser capaz de congelar un Kerbal. + #autoLOC_DF_00166 = Max. Temperatura. Mantener Kerbals congelados(K) + #autoLOC_DF_00167 = La temperatura máxima (en Kelvin) para un congelador\npara mantener Kerbal congelado. + #autoLOC_DF_00168 = Calor generado por kerbal (kW/min) + #autoLOC_DF_00169 = Cantidad de calor térmico (kW) generado\npor equipo para cada Kerbal por minuto congelado. + #autoLOC_DF_00170 = Proceso de congelación generado por calor(kW) + #autoLOC_DF_00171 = Cantidad de calor térmico (kW) generado\ncon cada deshielo/proceso de congelación. + #autoLOC_DF_00172 = Mostrar temperaturas de pieza en Kelvin + #autoLOC_DF_00173 = Si está encendido, Clic derecho de la parte mostrará la temperatura en Kelvin,\nsi setá apagado, se mostrará en Celsius. + #autoLOC_DF_00174 = Misc CongelaciónProfunda. + #autoLOC_DF_00175 = Encender luces del congelador + #autoLOC_DF_00176 = Apague si no quiere que las luces\del congelador internas funcionen. + #autoLOC_DF_00177 = Info sobre sugerencias + #autoLOC_DF_00178 = Activar y desactivar las sugerencias. + #autoLOC_DF_00179 = Filtro del editor + #autoLOC_DF_00180 = Activar y desactivar categoría del filtro CongelaciónProfunda. + #autoLOC_DF_00181 = Icono del lanzador de aplicaciones Stock + #autoLOC_DF_00182 = Si está encendido, El lanzador de Aplicación Stock se utilizará,\nsi está desactivada, utilizará la barra de herramientas de Blizzy si está instalada. + #autoLOC_DF_00183 = Registro extra de depuración + #autoLOC_DF_00184 = Activar esta opción para capturar gran cantidad de información adicional\nen el registro KSP para informar de un problema. + + #autoLOC_DF_00185 = CRY-0300 Cámara de congelación criónica + #autoLOC_DF_00186 = REPOSoftTech + #autoLOC_DF_00187 = Diseñado para el almacenamiento a largo plazo de 1 kerbal. El CRY-0300 utiliza Glykerol y carga eléctrica para congelar o descongelar un Kerbal. Asegúrese de que tiene suficiente capacidad de carga eléctrica en su nave. El CRY-0300 viene provisto de 10 unidades de Glykerol. PRECAUCIÓN: El CRY-0300 también requiere carga eléctrica por minuto por Kerbal para mantener su funcionamiento de sistemas de supervisión. Si no puede obtener esta carga eléctrica hay un riesgo de morir congelado. + #autoLOC_DF_00188 = Congelador criogénico congelaciónprofunda + #autoLOC_DF_00189 = CRY-0300R Cámara de congelación criónica + #autoLOC_DF_00190 = Diseñado para el almacenamiento a largo plazo de 1 kerbal. El CRY-0300R utiliza Glykerol y carga eléctrica para congelar o descongelar un Kerbal. Asegúrese de que tiene suficiente capacidad de carga eléctrica en su nave. El CRY-0300R viene provisto de 10 unidades de Glykerol. PRECAUCIÓN: El CRY-0300R también requiere carga eléctrica por minuto por Kerbal para mantener su funcionamiento de sistemas de supervisión. Si no puede obtener esta carga eléctrica hay un riesgo de morir congelado. + #autoLOC_DF_00191 = CRY-1300 Cámara de congelación criónica + #autoLOC_DF_00192 = Diseñado para el almacenamiento a largo plazo de 3 kerbals. El CRY-1300 utiliza Glykerol y carga eléctrica para congelar o descongelar un Kerbal. Asegúrese de que tiene suficiente capacidad de carga eléctrica en su nave. El CRY-1300 viene equipado con 15 unidades de Glykerol. PRECAUCIÓN: El CRY-1300 también requiere carga eléctrica por minuto por Kerbal para mantener su funcionamiento de sistemas de supervisión. Si no puede obtener esta carga eléctrica hay un riesgo de morir congelados. + #autoLOC_DF_00193 = CRY-2300 Cámara de congelación criónica + #autoLOC_DF_00194 = Diseñado para el almacenamiento a largo plazo de 10 kerbals. El CRY-2300 utiliza Glykerol y carga eléctrica para congelar o descongelar un Kerbal. Asegúrese de que tiene suficiente capacidad de carga eléctrica en su nave. El CRY-2300 viene abastecido con 50 unidades de Glykerol. PRECAUCIÓN: El CRY-2300 también requiere carga eléctrica por minuto por Kerbal para mantener su funcionamiento de los sistemas de supervisión. Si no puede obtener esta carga eléctrica hay un riesgo de morir congelados. + #autoLOC_DF_00195 = RS-X20R Contenedor de Glykerol + #autoLOC_DF_00196 = El RS-X20R es un contenedor Radial de Glykerol de pequeño volumen, para todas sus necesidades de congelación y descongelación Kerbal. Traído a usted por la gente buena en REPOSoftTech. Garantía anulada si se llena con Glykerol. + #autoLOC_DF_00197 = Tanque congelador criogénico de glicerol congelaciónprofunda + + #autoLOC_DF_00198 = Expertos en el campo de la criogenia, Ergonomía y equipos eléctricos, Los kerbals de REPOSoftTech están intentando difícilmente mantener todos los carenados de kerbals del espacio vivos y sus misiones aseguradas. + + #autoLOC_DF_00199 = Congelar <<1>> + #autoLOC_DF_00200 = Deshelar <<1>> + + #autoLOC_DF_00201 = Procesamiento de naves sin Carga + #autoLOC_DF_00202 = Si se habilita, CongelaciónProfunda procesará los recursos en las naves sin carga. Si está deshabilitado, no lo hará y jugará el juego de recuperación y estimación. + #autoLOC_DF_00203 = Beep Sounds On + #autoLOC_DF_00204 = If enabled Beep sounds are heard inside freezer parts with frozen kerbals. + #autoLOC_DF_00205 = Other Sounds On + #autoLOC_DF_00206 = If enabled all other DeepFreeze sounds are heard. + } +} + +Localization +{ + ja + { + #autoLOC_DF_00001 = <<1>> has recovered from emergency thaw and resumed normal duties. + #autoLOC_DF_00002 = <<1>> has been emergency thawed and cannot perform duties for <<2>> minutes. + #autoLOC_DF_00003 = DeepFreeze + #autoLOC_DF_00004 = DeepFreeze Vessel Switch + #autoLOC_DF_00005 = DeepFreeze Vessel Switch Failed + #autoLOC_DF_00006 = DeepFreeze Kerbals + #autoLOC_DF_00007 = DeepFreeze Alarms + #autoLOC_DF_00008 = Close Window + #autoLOC_DF_00009 = Vessel + #autoLOC_DF_00010 = Vessel Name + #autoLOC_DF_00011 = Part + #autoLOC_DF_00012 = Part Name + #autoLOC_DF_00013 = Tmp + #autoLOC_DF_00014 = Part Temperature Status + #autoLOC_DF_00015 = EC + #autoLOC_DF_00016 = Electric Charge Status + #autoLOC_DF_00017 = R.T + #autoLOC_DF_00018 = Remote Tech Status + #autoLOC_DF_00019 = Alarms + #autoLOC_DF_00020 = Press the button for Kerbal Alarm Clock Alarms assigned to this part + #autoLOC_DF_00021 = LastUpd + #autoLOC_DF_00022 = The Time the part was last updated + #autoLOC_DF_00023 = TimeRem + #autoLOC_DF_00024 = Approx. time remaining before Electric Charge will run out + #autoLOC_DF_00025 = Vessel <<1>> is Over-Heating. + #autoLOC_DF_00026 = OFF + #autoLOC_DF_00027 = S/BY + #autoLOC_DF_00028 = OUT + #autoLOC_DF_00029 = Vesssel <<1>> is out of ElectricCharge.\n Situation Critical. + #autoLOC_DF_00030 = ALRT + #autoLOC_DF_00031 = Vessel <<1>> is almost out of ElectricCharge. + #autoLOC_DF_00032 = LOW + #autoLOC_DF_00033 = OK + #autoLOC_DF_00034 = NC + #autoLOC_DF_00035 = Alarm + #autoLOC_DF_00036 = Go to Alarms + #autoLOC_DF_00037 = There are currently no Frozen Kerbals + #autoLOC_DF_00038 = Kerbal Name + #autoLOC_DF_00039 = Profession + #autoLOC_DF_00040 = Thaw + #autoLOC_DF_00041 = Thaw this kerbal + #autoLOC_DF_00042 = Cannot thaw <<1>> from KSC. Vessel still exists <<2>> at <<3>> + #autoLOC_DF_00043 = Freeze + #autoLOC_DF_00044 = Freeze this kerbal + #autoLOC_DF_00045 = KAC Alarms + #autoLOC_DF_00046 = Resize Window + #autoLOC_DF_00047 = <<1>>K + #autoLOC_DF_00048 = <<2>>C + #autoLOC_DF_00049 = <<1>> was stored frozen at KSC + #autoLOC_DF_00050 = Insufficient funds to thaw <<1>> at this time + #autoLOC_DF_00051 = <<1>> was found and thawed out + #autoLOC_DF_00052 = <<1>> was found and thawed out <<2>> funds deducted from account + #autoLOC_DF_00053 = Cannot thaw <<1>> vessel still exists <<2>> at <<3>> + + #autoLOC_DF_00054 = Freezer Capacity + #autoLOC_DF_00055 = Total Frozen Kerbals + #autoLOC_DF_00056 = Freezer Space + #autoLOC_DF_00057 = Part is Full? + #autoLOC_DF_00058 = R/T Connection + #autoLOC_DF_00059 = Freezer Temp + #autoLOC_DF_00060 = Cabin Temperature + #autoLOC_DF_00061 = K + #autoLOC_DF_00062 = DeepFreeze Menu + #autoLOC_DF_00063 = EC p/Kerbal to run + #autoLOC_DF_00064 = \u0020p/min + #autoLOC_DF_00065 = Current EC Usage + #autoLOC_DF_00066 = \u0020p/sec + #autoLOC_DF_00067 = Glykerol Reqd. to Freeze + #autoLOC_DF_00068 = EC p/Kerbal to Frze/Thaw + #autoLOC_DF_00069 = \nCryopods: <<1>> + #autoLOC_DF_00070 = C + #autoLOC_DF_00071 = Pod:<<1>> + #autoLOC_DF_00072 = Insufficient electric charge to monitor frozen kerbals. + #autoLOC_DF_00073 = \u0020Freezer Out of EC : Systems critical in <<1>> secs + #autoLOC_DF_00074 = <<1>> died due to lack of Electrical Charge to run cryogenics + #autoLOC_DF_00075 = Check Temperatures, Freezer getting hot + #autoLOC_DF_00076 = Warning!! Check Temperatures NOW, Freezer getting very hot + #autoLOC_DF_00077 = Temperature getting too hot for kerbals to remain frozen. + #autoLOC_DF_00078 = Freezer Over Temp : Systems critical in <<1>> secs + #autoLOC_DF_00079 = <<1>> died due to overheating, cannot keep frozen + #autoLOC_DF_00080 = Over Temperature - Emergency Thaw in Progress. + #autoLOC_DF_00081 = Insufficient electric charge to freeze kerbal + #autoLOC_DF_00082 = \u0020Cryopod - Charging: <<1>> + #autoLOC_DF_00083 = Insufficient Glykerol to freeze kerbal + #autoLOC_DF_00084 = Cannot Freeze while Temperature greater than <<1>> + #autoLOC_DF_00085 = Cannot Freeze while Crew Xfer in progress + #autoLOC_DF_00086 = Cannot run Freeze process on more than one Kerbal at a time + #autoLOC_DF_00087 = RemoteTech Detected. Press Freeze Again if you want to Freeze your Last Active Kerbal + #autoLOC_DF_00088 = An Active connection or Active Kerbal is Required On-Board to Initiate Thaw Process + #autoLOC_DF_00089 = Cannot freeze kerbal. Freezer is full + #autoLOC_DF_00090 = Cannot freeze kerbal at this time + #autoLOC_DF_00091 = Starting Freeze process + #autoLOC_DF_00092 = Freezing Aborted + #autoLOC_DF_00093 = <<1>> frozen + #autoLOC_DF_00094 = Insufficient electric charge to thaw kerbal + #autoLOC_DF_00095 = \u0020Cryopod - Charging:<<1>> + #autoLOC_DF_00096 = Cannot Thaw <<1>> Part is full + #autoLOC_DF_00097 = Cannot Thaw while Crew Xfer in progress + #autoLOC_DF_00098 = Cannot run Thaw process on more than one Kerbal at a time + #autoLOC_DF_00099 = Cannot thaw kerbal at this time + #autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + #autoLOC_DF_00101 = Thawing Aborted + #autoLOC_DF_00102 = <<1>> thawed out + #autoLOC_DF_00103 = <<1>> was thawed out due to lack of Electrical Charge to run cryogenics + #autoLOC_DF_00104 = DeepFreezer mechanical failure + #autoLOC_DF_00105 = Vessel about to change, Aborting Thaw process + #autoLOC_DF_00106 = Vessel about to change, Aborting Freeze process + + #autoLOC_DF_00107 = DeepFreeze Items + #autoLOC_DF_00108 = There is less than 5 units of Glykerol on-board for your DeepFreeze Freezers + #autoLOC_DF_00109 = A DeepFreeze Alarm event has occurred. Please Switch to <<1>> to execute. + #autoLOC_DF_00110 = DeepFreeze Alarm processing completed. + + #autoLOC_DF_00111 = Name + #autoLOC_DF_00112 = Alarm Name + #autoLOC_DF_00113 = Alarm Type + #autoLOC_DF_00114 = KAC Alarm Type + #autoLOC_DF_00115 = Time Remain. + #autoLOC_DF_00116 = Time remaining before Alarm is triggered + #autoLOC_DF_00117 = There are currently no KAC alarms associated to a DeepFreeze vessel + #autoLOC_DF_00118 = Delete + #autoLOC_DF_00119 = Delete this KAC alarm completely + #autoLOC_DF_00120 = Modify + #autoLOC_DF_00121 = Modify this Alarm + #autoLOC_DF_00122 = Save + #autoLOC_DF_00123 = Save Alarm Changes + #autoLOC_DF_00124 = Cannot Save Alarm. No R/Tech Connection to vessel. + #autoLOC_DF_00125 = DeepFreeze Alarm changes Saved. + #autoLOC_DF_00126 = DeepFreeze Cannot Save alarm changes, Time is up. + #autoLOC_DF_00127 = Cancel + #autoLOC_DF_00128 = Cancel any changes + #autoLOC_DF_00129 = Name + #autoLOC_DF_00130 = The Kerbals Name + #autoLOC_DF_00131 = Trait + #autoLOC_DF_00132 = The Kerbals Profession + #autoLOC_DF_00133 = Thaw + #autoLOC_DF_00134 = Thaw this kerbal on alarm activation + #autoLOC_DF_00135 = Freeze + #autoLOC_DF_00136 = Freeze this kerbal on alarm activation + #autoLOC_DF_00137 = Modify + #autoLOC_DF_00138 = Modify this Alarms settings + + #autoLOC_DF_00139 = Switch to Vessel + #autoLOC_DF_00140 = Not Now + #autoLOC_DF_00141 = Don't switch vessel now + #autoLOC_DF_00142 = Automatic Switch to vessel failed.\nPlease switch manually to vessel Immediately + #autoLOC_DF_00143 = Switch to DeepFreeze vessel required + + #autoLOC_DF_00144 = DeepFreeze Options + #autoLOC_DF_00145 = ElectricCharge Required to run Freezers + #autoLOC_DF_00146 = If on, EC is required to run freezers + #autoLOC_DF_00147 = Fatal EC/Heat Option + #autoLOC_DF_00148 = If on Kerbals will die if EC runs out or it gets too hot + #autoLOC_DF_00149 = Non Fatal Comatose Time(in secs) + #autoLOC_DF_00150 = The time in seconds a kerbal is comatose\n if fatal EC / Heat option is off + #autoLOC_DF_00151 = AutoRecover Frozen Kerbals at KSC + #autoLOC_DF_00152 = If on, will AutoRecover Frozen Kerbals at the KSC\n and deduct the Cost from your funds + #autoLOC_DF_00153 = Cost to Thaw a Kerbal at KSC + #autoLOC_DF_00154 = Amt of currency Reqd to Freeze a Kerbal from the KSC + #autoLOC_DF_00155 = EC Reqd to Freeze/Thaw a Kerbal + #autoLOC_DF_00156 = Amt of ElecCharge Reqd to Freeze/Thaw a Kerbal. + #autoLOC_DF_00157 = Glykerol Reqd to Freeze a Kerbal + #autoLOC_DF_00158 = Amt of Glykerol used to Freeze a Kerbal,\nOverrides Part values. + #autoLOC_DF_00159 = DeepFreeze Temperatures + #autoLOC_DF_00160 = Get your calculator out. + #autoLOC_DF_00161 = Temps are in (K)elvin. (K) = (C)elcius + 273.15. (K) = ((F)arenheit + 459.67) × 5/9. Get your calculator out + #autoLOC_DF_00162 = Regulated Temperatures Required + #autoLOC_DF_00163 = If on, Regulated Temps apply to freeze\nand keep Kerbals Frozen. + #autoLOC_DF_00164 = Min. Temp. for Freezer to Freeze(K) + #autoLOC_DF_00165 = The minimum temperature (in Kelvin) for a Freezer\nto be able to Freeze a Kerbal. + #autoLOC_DF_00166 = Max. Temp. to keep Kerbals Frozen(K) + #autoLOC_DF_00167 = The maximum temperature (in Kelvin) for a Freezer\nto keep Kerbals frozen. + #autoLOC_DF_00168 = Heat generated per kerbal (kW/min) + #autoLOC_DF_00169 = Amount of thermal heat (kW) generated\nby equipment for each frozen kerbal per minute. + #autoLOC_DF_00170 = Heat generated freezer process(kW) + #autoLOC_DF_00171 = Amount of thermal heat (kW) generated\nwith each thaw/freeze process. + #autoLOC_DF_00172 = Show Part Temperatures in Kelvin + #autoLOC_DF_00173 = If on Part right click will show temp in Kelvin,\nif Off will show in Celcius. + #autoLOC_DF_00174 = DeepFreeze Misc. + #autoLOC_DF_00175 = Freezer Strip Lights On + #autoLOC_DF_00176 = Turn off if you do not want the internal\nfreezer strip lights to function. + #autoLOC_DF_00177 = ToolTips On + #autoLOC_DF_00178 = Turn the Tooltips on and off. + #autoLOC_DF_00179 = Editor Filter + #autoLOC_DF_00180 = Turn the DeepFreeze Editor filter Category on and off. + #autoLOC_DF_00181 = Use Stock App Launcher Icon + #autoLOC_DF_00182 = If on, the Stock Application launcher will be used,\nif off will use Blizzy Toolbar if installed. + #autoLOC_DF_00183 = Extra Debug Logging + #autoLOC_DF_00184 = Turn this On to capture lots of extra information\ninto the KSP log for reporting a problem. + + #autoLOC_DF_00185 = CRY-0300 Cryonic Freezing Chamber + #autoLOC_DF_00186 = REPOSoftTech + #autoLOC_DF_00187 = Designed for long term storage of 1 kerbal. The CRY-0300 uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-0300 comes stocked with 10 units of Glykerol. CAUTION: The CRY-0300 also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00188 = deepfreeze cryogenic freezer + #autoLOC_DF_00189 = CRY-0300R Cryonic Freezing Chamber + #autoLOC_DF_00190 = Designed for long term storage of 1 kerbal. The CRY-0300R uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-0300R comes stocked with 10 units of Glykerol. CAUTION: The CRY-0300R also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00191 = CRY-1300 Cryonic Freezing Chamber + #autoLOC_DF_00192 = Designed for long term storage of up to 3 Kerbals. The CRY-1300 uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-1300 comes stocked with 15 units of Glykerol. CAUTION: The CRY-1300 also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00193 = CRY-2300 Cryonic Freezing Chamber + #autoLOC_DF_00194 = Designed for long term storage of up to 10 Kerbals. The CRY-2300 uses Glykerol and ElectricCharge to freeze or thaw one Kerbal. Please ensure you have enough ElectricCharge capacity on your ship. The CRY-2300 comes stocked with 50 units of Glykerol. CAUTION: The CRY-2300 also requires ElectricCharge per minute per Kerbal to keep it's Monitoring Systems Functioning. If it cannot get this ElectricCharge there is a risk of frozen Kerbals dying. + #autoLOC_DF_00195 = RS-X20R Glykerol Container + #autoLOC_DF_00196 = The RS-X20R is a small-volume Radial Glykerol container, for all your Kerbal Freezing and Thawing needs. Brought to you by the good folks at REPOSoftTech. Warranty void if filled with Glykerol. + #autoLOC_DF_00197 = deepfreeze cryogenic freezer glykerol tank + + #autoLOC_DF_00198 = Experts in the field of cryogenics, ergonomics and electrical equipment, the kerbals at REPOSoftTech are trying hard to keep all space fairing kerbals alive and their missions successful. + + #autoLOC_DF_00199 = Freeze <<1>> + #autoLOC_DF_00200 = Thaw <<1>> + + #autoLOC_DF_00201 = Unloaded Vessel Processing + #autoLOC_DF_00202 = If enabled DeepFreeze will process resources on unloaded vessels. If disabled, it won't and play the catchup and estimation game. + #autoLOC_DF_00203 = Beep Sounds On + #autoLOC_DF_00204 = If enabled Beep sounds are heard inside freezer parts with frozen kerbals. + #autoLOC_DF_00205 = Other Sounds On + #autoLOC_DF_00206 = If enabled all other DeepFreeze sounds are heard. + } +} + +Localization +{ + ru + { + #autoLOC_DF_00001 = <<1>> оправился от чрезвычайных разморозок и возобновил выполнение своих обычных обязанностей. + #autoLOC_DF_00002 = <<1>> была аварийная разморозка, не сможет выполнять свои обязанности <<2>> минут. + #autoLOC_DF_00003 = Анабиоз + #autoLOC_DF_00004 = Смотреть аппарат анабиоза + #autoLOC_DF_00005 = Ошибка переключения на аппарат анабиоза + #autoLOC_DF_00006 = Kербалы в анабиозе + #autoLOC_DF_00007 = Часы анабиоза + #autoLOC_DF_00008 = Закрыть окно + #autoLOC_DF_00009 = Аппарат + #autoLOC_DF_00010 = Название аппарата + #autoLOC_DF_00011 = Аппарат + #autoLOC_DF_00012 = Название части + #autoLOC_DF_00013 = Темп. + #autoLOC_DF_00014 = Статус температуры + #autoLOC_DF_00015 = Электр. + #autoLOC_DF_00016 = Статус электричества + #autoLOC_DF_00017 = Р.Т + #autoLOC_DF_00018 = Р.Т. статус + #autoLOC_DF_00019 = Часы + #autoLOC_DF_00020 = Нажмите кнопку сигнала тревоги для будильника, назначенные к этой части + #autoLOC_DF_00021 = Последнее обновл. + #autoLOC_DF_00022 = Время было обновлено + #autoLOC_DF_00023 = Время + #autoLOC_DF_00024 = Приблизительно. Время, оставшиеся до электрического импульса + #autoLOC_DF_00025 = Аппарат <<1>> перегрелся. + #autoLOC_DF_00026 = ВЫКЛ. + #autoLOC_DF_00027 = S/BY + #autoLOC_DF_00028 = КОНЧИЛОСЬ + #autoLOC_DF_00029 = Аппарат <<1>> не имеет электричества.\n Критическая ситуация. + #autoLOC_DF_00030 = ЧАСЫ + #autoLOC_DF_00031 = Аппарат <<1>> подключён к электросети. + #autoLOC_DF_00032 = НИЗКО + #autoLOC_DF_00033 = ОК + #autoLOC_DF_00034 = NC + #autoLOC_DF_00035 = Часы + #autoLOC_DF_00036 = К часам + #autoLOC_DF_00037 = В настоящее время нет замороженных Кербалов + #autoLOC_DF_00038 = Имя Кербала + #autoLOC_DF_00039 = Профессия + #autoLOC_DF_00040 = Размор. + #autoLOC_DF_00041 = Размор. этого Кербала + #autoLOC_DF_00042 = Нельзя разморозить <<1>> около КСЦ. Аппарат по-прежнему существует <<2>> в <<3>> + #autoLOC_DF_00043 = Замор. + #autoLOC_DF_00044 = Замор. этого Кербала + #autoLOC_DF_00045 = KAC часы + #autoLOC_DF_00046 = Изменить окно + #autoLOC_DF_00047 = <<1>>K + #autoLOC_DF_00048 = <<2>>C + #autoLOC_DF_00049 = <<1>> был заморожен(а) около КСЦ + #autoLOC_DF_00050 = Недостаточно средств, чтобы разморозить <<1>> в это время + #autoLOC_DF_00051 = <<1>> Обнаружен и разморожен + #autoLOC_DF_00052 = <<1>> обнаружен и разморожен <<2>> средства списываются со счёта + #autoLOC_DF_00053 = Нельзя разморозить <<1>>, аппарат по-прежнему существует <<2>> в <<3>> + + #autoLOC_DF_00054 = Вместимость для анабиоза + #autoLOC_DF_00055 = Всех замороженных Кербалов + #autoLOC_DF_00056 = Всего можно заморозить + #autoLOC_DF_00057 = Кабина полная? + #autoLOC_DF_00058 = Р.Т. соединение + #autoLOC_DF_00059 = Температура для заморозки + #autoLOC_DF_00060 = Температура кабины + #autoLOC_DF_00061 = K + #autoLOC_DF_00062 = Меню анабиоза + #autoLOC_DF_00063 = Нужное кол-во ед. электр. для запуска + #autoLOC_DF_00064 = \u0020p/мин + #autoLOC_DF_00065 = Кол-во используемой энергии. + #autoLOC_DF_00066 = \u0020p/сек + #autoLOC_DF_00067 = Нужное кол-во гликерола для заморозки + #autoLOC_DF_00068 = Электр. для заморозки/разморозки Кербала + #autoLOC_DF_00069 = \nКабина: <<1>> + #autoLOC_DF_00070 = C + #autoLOC_DF_00071 = Кабина:<<1>> + #autoLOC_DF_00072 = Недостаточно энергии для мониторинга замороженных кербалов. + #autoLOC_DF_00073 = \u0020Камера не имеет энергии: критическая ситуация на <<1>> секунд(ы) + #autoLOC_DF_00074 = <<1>> умер из-за отсутствия энергии для запуска камеры + #autoLOC_DF_00075 = Проверьте температуру, в камере становится жарко + #autoLOC_DF_00076 = ВНИМАНИЕ! Проверьте температуру СЕЙЧАС, в камере очень жарко! + #autoLOC_DF_00077 = Температура становится слишком высокой для кербалов, чтобы оставаться в анабиозе. + #autoLOC_DF_00078 = Камера перегрета: критическая ситуация на <<1>> секунд(ы) + #autoLOC_DF_00079 = <<1>> умер из-за перегрева, невозможно содержать в анабиозе + #autoLOC_DF_00080 = Перегрев - аварийная разморозка в процессе. + #autoLOC_DF_00081 = Недостаточно электричества для заморозки Кербала + #autoLOC_DF_00082 = \u0020Расход электричества: <<1>> + #autoLOC_DF_00083 = Недостаточно гликерола для заморозки Кербала + #autoLOC_DF_00084 = Нельзя заморозить, пока темп. не станет ниже чем <<1>> + #autoLOC_DF_00085 = Нельзя заморозить, пока переместитель экипажа работает + #autoLOC_DF_00086 = Невозможно запустить процесс замораживания более одного Кербала в это время + #autoLOC_DF_00087 = Р.Т. обнаружен. Нажмите "Заморозить", если вы хотите заморозить своего последнего активного Кербала. + #autoLOC_DF_00088 = Активное соединение или активный Кербал на борту, чтобы начать процесс разморозки + #autoLOC_DF_00089 = Нельзя заморозить Кербала. Кабина полная + #autoLOC_DF_00090 = Нельзя разморозить Кербала в это время + #autoLOC_DF_00091 = Идет процесс заморозки + #autoLOC_DF_00092 = Заморозка отменена + #autoLOC_DF_00093 = <<1>> заморожен(а) + #autoLOC_DF_00094 = Недостаточно электричества для разморозки Кербала + #autoLOC_DF_00095 = \u0020Расход электричества:<<1>> + #autoLOC_DF_00096 = Нельзя разморозить <<1>>, кабина полная + #autoLOC_DF_00097 = Нельзя разморозить пока переместитель экипажа в процессе + #autoLOC_DF_00098 = Нельзя размораживать более одного Кербала в одно и то же время + #autoLOC_DF_00099 = Нельзя разморозить Кербала в это время + #autoLOC_DF_00100 = Ошибка кода: нельзя разморозить Кербала. Проверьте логи + #autoLOC_DF_00101 = Разморозка отменена + #autoLOC_DF_00102 = <<1>> разморожен(а) + #autoLOC_DF_00103 = <<1>> был разморожен из-за отсутствия электричества для запуска криогеника + #autoLOC_DF_00104 = Камера имеет механическое повреждение + #autoLOC_DF_00105 = Аппарат изменился, прерывание процесса разморозки + #autoLOC_DF_00106 = Аппарат изменился, прерывание процесса заморозки + + #autoLOC_DF_00107 = На тему анабиоза + #autoLOC_DF_00108 = Осталось менее 5 единиц гликерола для анабиоза + #autoLOC_DF_00109 = Произошла тревога при заморозке. Пожалуйста, переключитесь на <<1>>, чтобы выполнить. + #autoLOC_DF_00110 = Обработка будильника завершена. + + #autoLOC_DF_00111 = Имя + #autoLOC_DF_00112 = Название часов + #autoLOC_DF_00113 = Тип часов + #autoLOC_DF_00114 = KAC тип часов + #autoLOC_DF_00115 = Оставшееся время + #autoLOC_DF_00116 = Оставшееся время до тревоги + #autoLOC_DF_00117 = В настоящее время нет KAC часов, связанных с камерой + #autoLOC_DF_00118 = Удалить + #autoLOC_DF_00119 = Удалите эти KAC часы полностью + #autoLOC_DF_00120 = Изменить + #autoLOC_DF_00121 = Изменить эти часы + #autoLOC_DF_00122 = Сохранить + #autoLOC_DF_00123 = Сохранить изменения часов + #autoLOC_DF_00124 = Невозможно сохранить часы. Отсутствует сигнал Р.Т. + #autoLOC_DF_00125 = Сохранить изменения часов анабиоза. + #autoLOC_DF_00126 = Анабиоз не может сохранить изменения часов, время истекло. + #autoLOC_DF_00127 = Отменить + #autoLOC_DF_00128 = Отменить изменения + #autoLOC_DF_00129 = Имя + #autoLOC_DF_00130 = Имя Кербала + #autoLOC_DF_00131 = Черта + #autoLOC_DF_00132 = Профессия Кербала + #autoLOC_DF_00133 = Разморозить + #autoLOC_DF_00134 = Разморозить этого Кербала по активации часов + #autoLOC_DF_00135 = Заморозить + #autoLOC_DF_00136 = Разморозить этого Кербала по активации часов + #autoLOC_DF_00137 = Изменить + #autoLOC_DF_00138 = Изменить настройки этих часов + + #autoLOC_DF_00139 = Переключиться на аппарат + #autoLOC_DF_00140 = Не сейчас + #autoLOC_DF_00141 = Невозможно переключиться на аппарат + #autoLOC_DF_00142 = Автоматическое переключение на аппарат не удалось.\nПожалуйста переключитесь вручную. + #autoLOC_DF_00143 = Требуется переключение на камеру + + #autoLOC_DF_00144 = Опции анабиоза + #autoLOC_DF_00145 = Необходимое кол-во энергии для запуска камеры + #autoLOC_DF_00146 = Если включено, энергии нужно для запуска камеры + #autoLOC_DF_00147 = Макс. энергии/тепло + #autoLOC_DF_00148 = Кербал умрет, если подача энергии прекратится или станет слишком жарко. + #autoLOC_DF_00149 = Некритическое коматозное время (в сек) + #autoLOC_DF_00150 = Время комы Кербала в секундах\n если отсутствует энергия/тепло отключено + #autoLOC_DF_00151 = Автовозвращение замороженных Кербалов в КСЦ + #autoLOC_DF_00152 = Если включено, будет авто-возвращение замороженных Кербалов в КСЦ\n и будет списание средств со счета. + #autoLOC_DF_00153 = Стоимость разморозки Кербала в КСЦ + #autoLOC_DF_00154 = Нужное кол-во валюты для заморозки Кербала в КСЦ + #autoLOC_DF_00155 = Нужное кол-во энергии для заморозки/разморозки Кербала + #autoLOC_DF_00156 = Нужное кол-во энергии для заморозки/разморозки Кербала в КСЦ + #autoLOC_DF_00157 = Нужное кол-во гликерола для заморозки/разморозки Кербала + #autoLOC_DF_00158 = Нужное кол-во гликерола для заморозки,\nПерекрывает часть цены. + #autoLOC_DF_00159 = Температура анабиоза + #autoLOC_DF_00160 = Получите свой калькулятор. + #autoLOC_DF_00161 = Темп. по (K)ельвину. (K) = (Ц)ельсия + 273.15. (K) = ((Ф)аренгейт + 459.67) × 5/9. Получите свой калькулятор. + #autoLOC_DF_00162 = Необходимая постоянная температура + #autoLOC_DF_00163 = Если включено, энергия применяется для заморозки/удержания Кербалов в заморозке. + #autoLOC_DF_00164 = Минимальная температура для заморозки (K) + #autoLOC_DF_00165 = Минимальная температура (по Кельвину) для заморозки Кербала. + #autoLOC_DF_00166 = Максимальная температура для поддержания заморозки (K) + #autoLOC_DF_00167 = Максимальная температура (по Кельвину) для заморозки Кербала/поддержания заморозки. + #autoLOC_DF_00168 = Тепло, выделяемое для Кербала (кВт/мин) + #autoLOC_DF_00169 = Объем тепловой энергии (кВт), создаваемый оборудованием\n для каждого замороженного Кербала в минуту. + #autoLOC_DF_00170 = Тепло, выделяемое камере(кВт) + #autoLOC_DF_00171 = Объем тепловой энергии (кВт)\n на каждый процесс размораживания/замораживания. + #autoLOC_DF_00172 = Показать температуру частей по Кельвину + #autoLOC_DF_00173 = Если при нажатии ПКМ показывает темп. по Кельвину,\n если выключите, будет показывать в Цельсия. + #autoLOC_DF_00174 = Накл. анабиоз + #autoLOC_DF_00175 = Включить свет + #autoLOC_DF_00176 = Выключите, если Вы не хотите, чтобы свет интерьера\n функционировал. + #autoLOC_DF_00177 = Вкл. подсказки + #autoLOC_DF_00178 = Включите подсказки и выключите. + #autoLOC_DF_00179 = Редактор фильтра + #autoLOC_DF_00180 = Включите редактор анабиоза-категории фильтров. + #autoLOC_DF_00181 = Использовать значок стокового лаунчера. + #autoLOC_DF_00182 = Если включено, стоковый лаунчер будет использоваться,\n если выключены, будет использоваться Blizzy Toolbar, если установлен. + #autoLOC_DF_00183 = Дополнительные дебаги + #autoLOC_DF_00184 = Включите это, чтобы взять множество дополнительной информации\n в КСП отчет для представления проблемы. + + #autoLOC_DF_00185 = КРИ-0300 + #autoLOC_DF_00186 = РЕПОСофтТэк + #autoLOC_DF_00187 = Предназначен для длительного погружения в анабиоз 1 кербала. КРИ-0300 использует гликерол и энергию, чтобы заморозить или разморозить одного Кербала. Пожалуйста, убедитесь, достаточно ли у вас энергии на корабле. К КРИ-0300 поставляется с 10 единицами гликерола. Осторожно: ВНИМАНИЕ: КРИ-0300 также расходует Электроэнергию ежеминутно для отслеживания жизненных показателей каждого размещённого кербала. Если Электроэнергии для этих целей не хватит, есть риск, что кербалы умрут. + #autoLOC_DF_00188 = deepfreeze cryogenic freezer + #autoLOC_DF_00189 = КРИ-0300Р + #autoLOC_DF_00190 = Предназначен для длительного погружения в анабиоз 1 кербала. КРИ-0300Р использует гликерол и энергию, чтобы заморозить или разморозить одного Кербала. Пожалуйста, убедитесь, достаточно ли у вас энергии на корабле. К КРИ-0300Р поставляется с 10 единицами гликерола. ВНИМАНИЕ: КРИ-0300Р также расходует Электроэнергию ежеминутно для отслеживания жизненных показателей каждого размещённого кербала. Если электроэнергии для этих целей не хватит, есть риск, что кербалы умрут. + #autoLOC_DF_00191 = КРИ-1300 + #autoLOC_DF_00192 = Предназначен для длительного погружения в анабиоз 3 кербала. КРИ-1300 использует гликерол и энергию, чтобы заморозить или разморозить одного Кербала. Пожалуйста, убедитесь, достаточно ли у вас энергии на корабле. К КРИ-1300 поставляется с 15 единицами гликерола. ВНИМАНИЕ: КРИ-1300 также расходует электроэнергию ежеминутно для отслеживания жизненных показателей каждого размещённого кербала. Если Электроэнергии для этих целей не хватит, есть риск, что кербалы умрут. + #autoLOC_DF_00193 = КРИ-2300 + #autoLOC_DF_00194 = Предназначен для длительного погружения в анабиоз 10 кербала. КРИ-2300 использует гликерол и энергию, чтобы заморозить или разморозить одного Кербала. Пожалуйста, убедитесь, достаточно ли у вас энергии на корабле. К КРИ-2300 поставляется с 50 единицами гликерола. ВНИМАНИЕ: КРИ-2300 также расходует электроэнергию ежеминутно для отслеживания жизненных показателей каждого размещённого кербала. Если Электроэнергии для этих целей не хватит, есть риск, что кербалы умрут. + #autoLOC_DF_00195 = Радиальный бак с гликеролом + #autoLOC_DF_00196 = РС-X20R-это небольшие по объему радиальные контейнеры для удовлетворения нужд по вводу или выводу кербонавтов из анабиоза. + #autoLOC_DF_00197 = deepfreeze cryogenic freezer glykerol tank + + #autoLOC_DF_00198 = Эксперты в области криогеники, эргономики и электрооборудования, а также кербалы в РЕПОСофтТех очень стараются держать все пространство кербалов живым и их миссии успешными. + + #autoLOC_DF_00199 = Заморозить <<1>> + #autoLOC_DF_00200 = Разморозить <<1>> + + #autoLOC_DF_00201 = Обработка выгруженных КА + #autoLOC_DF_00202 = Если включено, анабиоз будет считать ресурсы выгруженных космических аппаратов. \n Если выключено, TAC LS не будет просчитывать ресурсы таких космических аппаратов в игре. \nВыгруженный космический аппарат не управляется непосредственно \nи находится очень далеко от активного КА, поэтому, для экономии ресурсов, игра просчитывает для него \nТОЛЬКО орбитальную механику и некоторые другие параметры. + #autoLOC_DF_00203 = Beep Sounds On + #autoLOC_DF_00204 = If enabled Beep sounds are heard inside freezer parts with frozen kerbals. + #autoLOC_DF_00205 = Other Sounds On + #autoLOC_DF_00206 = If enabled all other DeepFreeze sounds are heard. + } +} + +Localization +{ + zh-cn + { + #autoLOC_DF_00001 = <<1>> 已从低温休眠中恢复,正常工作。 + #autoLOC_DF_00002 = <<1>> 紧急恢复,不能在 <<2>> 分钟内工作。 + #autoLOC_DF_00003 = 低温休眠 + #autoLOC_DF_00004 = 低温休眠载具切换 + #autoLOC_DF_00005 = 低温休眠载具切换失效 + #autoLOC_DF_00006 = 低温休眠小绿人 + #autoLOC_DF_00007 = 低温休眠警报 + #autoLOC_DF_00008 = 关闭窗口 + #autoLOC_DF_00009 = 载具 + #autoLOC_DF_00010 = 载具名称 + #autoLOC_DF_00011 = 组件 + #autoLOC_DF_00012 = 组件名称 + #autoLOC_DF_00013 = 温度 + #autoLOC_DF_00014 = 组件温度状态 + #autoLOC_DF_00015 = 电池 + #autoLOC_DF_00016 = 电池状态 + #autoLOC_DF_00017 = R。T + #autoLOC_DF_00018 = 通信状态 + #autoLOC_DF_00019 = 警报 + #autoLOC_DF_00020 = 为小绿人闹钟警报按下按钮给这个部分报警 + #autoLOC_DF_00021 = 最后一次更新 + #autoLOC_DF_00022 = 最近一次更新部件的时间 + #autoLOC_DF_00023 = 持续时间 + #autoLOC_DF_00024 = 在电量耗尽之前剩下的时间 + #autoLOC_DF_00025 = 载具 <<1>> 过热。 + #autoLOC_DF_00026 = 关闭 + #autoLOC_DF_00027 = S/BY + #autoLOC_DF_00028 = 耗尽 + #autoLOC_DF_00029 = 载具<<1>> 已经耗尽所有电量。\n 十万火急。 + #autoLOC_DF_00030 = ALRT + #autoLOC_DF_00031 = 载具 <<1>> 几乎耗尽电量。 + #autoLOC_DF_00032 = 低 + #autoLOC_DF_00033 = 好 + #autoLOC_DF_00034 = NC + #autoLOC_DF_00035 = 警报 + #autoLOC_DF_00036 = 去报警 + #autoLOC_DF_00037 = 目前还没有休眠小绿人 + #autoLOC_DF_00038 = 小绿人名称 + #autoLOC_DF_00039 = 职业 + #autoLOC_DF_00040 = 唤醒 + #autoLOC_DF_00041 = 唤醒这个小绿人 + #autoLOC_DF_00042 = 没有办法唤醒 <<1>> 从KSC。 载具仍然在 <<2>> 到 <<3>> + #autoLOC_DF_00043 = 休眠 + #autoLOC_DF_00044 = 休眠这个小绿人 + #autoLOC_DF_00045 = KAC 警报 + #autoLOC_DF_00046 = 调整窗口 + #autoLOC_DF_00047 = <<1>>K + #autoLOC_DF_00048 = <<2>>C + #autoLOC_DF_00049 = <<1>> 存储在KSC休眠 + #autoLOC_DF_00050 = 目前唤醒<<1>>的资金不足 + #autoLOC_DF_00051 = <<1>> 发现并唤醒 + #autoLOC_DF_00052 = <<1>> 发现并唤醒从账户里扣除 <<2>> 资金 + #autoLOC_DF_00053 = 唤醒无效 <<1>> 载具仍然存在 <<2>> 在 <<3>> + + #autoLOC_DF_00054 = 休眠室容量 + #autoLOC_DF_00055 = 休眠小绿人总量 + #autoLOC_DF_00056 = 休眠室空间 + #autoLOC_DF_00057 = 组件是完整的吗? + #autoLOC_DF_00058 = R/T 连接 + #autoLOC_DF_00059 = 休眠室温度 + #autoLOC_DF_00060 = 客舱温度 + #autoLOC_DF_00061 = K + #autoLOC_DF_00062 = 低温休眠的菜单 + #autoLOC_DF_00063 = EC p/小绿人 在运行 + #autoLOC_DF_00064 = \u0020p/min + #autoLOC_DF_00065 = 当前电量使用 + #autoLOC_DF_00066 = \u0020p/sec + #autoLOC_DF_00067 = 糖醇 Reqd。 to Freeze + #autoLOC_DF_00068 = EC p/小绿人 to Frze/Thaw + #autoLOC_DF_00069 = \nCryopods: <<1>> + #autoLOC_DF_00070 = C + #autoLOC_DF_00071 = Pod:<<1>> + #autoLOC_DF_00072 = 电量不足,监测到无法冰冻小绿人s。 + #autoLOC_DF_00073 = \u0020休眠室电荷输出 : Systems critical in <<1>> secs + #autoLOC_DF_00074 = <<1>> 由于缺乏运行低温的电荷而死亡 + #autoLOC_DF_00075 = 检查温度,休眠室变热 + #autoLOC_DF_00076 = 警告! !现在检查温度,休眠室变热了 + #autoLOC_DF_00077 = 温度太高,小绿人s无法保持冰冻状态。 + #autoLOC_DF_00078 = Freezer Over Temp : Systems critical in <<1>> secs + #autoLOC_DF_00079 = <<1>> 死于过热,不能保持冷冻 + #autoLOC_DF_00080 = 温度过高-紧急解冻正在进行中 + #autoLOC_DF_00081 = 没有足够的电荷来冻结小绿人s + #autoLOC_DF_00082 = \u0020Cryopod - Charging: <<1>> + #autoLOC_DF_00083 = 没有足够的糖醇来冷冻小绿人 + #autoLOC_DF_00084 = 温度超过时不能结冰 <<1>> + #autoLOC_DF_00085 = 在乘员前进过程中不能冻结 + #autoLOC_DF_00086 = 不能同时在多个小绿人上运行冻结进程 + #autoLOC_DF_00087 = RemoteTech检测到,如果您想冻结您最后一次活动的小绿人,请再次按下Freeze + #autoLOC_DF_00088 = 需要一个主动连接或主动的小绿人启动解冻过程 + #autoLOC_DF_00089 = 无法冻结小绿人。休眠室是满的 + #autoLOC_DF_00090 = 此时无法冻结小绿人 + #autoLOC_DF_00091 = 开始冻结过程 + #autoLOC_DF_00092 = 冻结中止 + #autoLOC_DF_00093 = <<1>> 冻 + #autoLOC_DF_00094 = 没有足够的电荷使小绿人解冻 + #autoLOC_DF_00095 = \u0020Cryopod - Charging:<<1>> + #autoLOC_DF_00096 = 不能解冻 <<1>> 部分是完整的 + #autoLOC_DF_00097 = 船员在进行中不能解冻 + #autoLOC_DF_00098 = 一次不能在多个小绿人上运行解冻过程 + #autoLOC_DF_00099 = 此时无法解冻小绿人 + #autoLOC_DF_00100 = 代码错误:此时无法解冻小绿人,请检查日志 + #autoLOC_DF_00101 = 解冻中止 + #autoLOC_DF_00102 = <<1>> 解冻了 + #autoLOC_DF_00103 = <<1>> 由于缺乏运行低温的电荷而被解冻 + #autoLOC_DF_00104 = 休眠室机械故障 + #autoLOC_DF_00105 = 船只即将更换,正在中止解冻过程 + #autoLOC_DF_00106 = 船只即将改变,中止冻结过程 + + #autoLOC_DF_00107 = 深度冻结项目 + #autoLOC_DF_00108 = 你的休眠室上的糖醇少于5个单位 + #autoLOC_DF_00109 = 发生深度冻结报警事件。请切换到<<1>>执行。 + #autoLOC_DF_00110 = 深度冻结报警处理完成。 + + #autoLOC_DF_00111 = 姓名 + #autoLOC_DF_00112 = 报警的名 + #autoLOC_DF_00113 = 报警类型 + #autoLOC_DF_00114 = KAC报警类型 + #autoLOC_DF_00115 = 剩余时间 + #autoLOC_DF_00116 = 触发警报前的剩余时间 + #autoLOC_DF_00117 = 目前没有与深度冷冻容器相关联的KAC警报 + #autoLOC_DF_00118 = 删除 + #autoLOC_DF_00119 = 完全删除这个KAC警报 + #autoLOC_DF_00120 = 修改 + #autoLOC_DF_00121 = 修改此警报 + #autoLOC_DF_00122 = 保存 + #autoLOC_DF_00123 = 保存警报更改 + #autoLOC_DF_00124 = 无法保存警报。与船舶没有信号联系。 + #autoLOC_DF_00125 = 保存深度冻结报警的更改 + #autoLOC_DF_00126 = 深度冻结无法保存报警更改,时间已到。 + #autoLOC_DF_00127 = 取消 + #autoLOC_DF_00128 = 取消任何更改 + #autoLOC_DF_00129 = 名字 + #autoLOC_DF_00130 = 小绿人s名称 + #autoLOC_DF_00131 = 特征 + #autoLOC_DF_00132 = 小绿人s专业 + #autoLOC_DF_00133 = 解冻 + #autoLOC_DF_00134 = 在警报激活时解冻此小绿人 + #autoLOC_DF_00135 = 冻结 + #autoLOC_DF_00136 = 在警报激活时冻结这个小绿人 + #autoLOC_DF_00137 = 修改 + #autoLOC_DF_00138 = 修改此警报设置 + + #autoLOC_DF_00139 = 载具切换 + #autoLOC_DF_00140 = 现在不行 + #autoLOC_DF_00141 = 现在不可以切换载具 + #autoLOC_DF_00142 = 自动切换载具失败。\n请立即手动切换到载具。 + #autoLOC_DF_00143 = 切换到低温休眠室 + + #autoLOC_DF_00144 = 低温休眠选项 + #autoLOC_DF_00145 = 运行休眠室所需的电量 + #autoLOC_DF_00146 = 如果启动,运行休眠室是需要电力的 + #autoLOC_DF_00147 = 致命的电力/热选项 + #autoLOC_DF_00148 = 如果温度太高或者电量耗尽,小绿人就会死亡 + #autoLOC_DF_00149 = 非致命昏迷时间(秒) + #autoLOC_DF_00150 = 如果有致命的事故发生,那么在几秒钟内,一个小绿人就会昏迷 + #autoLOC_DF_00151 = 在KSC自动休眠小绿人 + #autoLOC_DF_00152 = 如果打开的话,将在KSC中自动进行休眠,并从你的基金中扣除费用 + #autoLOC_DF_00153 = 在KSC唤醒一个小绿人的成本 + #autoLOC_DF_00154 = 在KSC休眠一个小绿人的成本 + #autoLOC_DF_00155 = 重新使用电力休眠/唤醒一个小绿人 + #autoLOC_DF_00156 = 冷冻/解冻小绿人所需的电荷量。 + #autoLOC_DF_00157 = 糖醇来冻结一个小绿人 + #autoLOC_DF_00158 = 用于冻结小绿人的糖醇的Amt,\n覆盖部分值 + #autoLOC_DF_00159 = 深度冻结温度 + #autoLOC_DF_00160 = 拿出计算器。 + #autoLOC_DF_00161 = 计算在(K)elvin。 (K) = (C)elcius + 273。15。 (K) = ((F)arenheit + 459。67) × 5/9。 拿出计算器 + #autoLOC_DF_00162 = 所需调节温度 + #autoLOC_DF_00163 = 如果打开,则调节温度应用于冻结\n和保持路边结冰。 + #autoLOC_DF_00164 = 休眠室冷冻所需的最低温度(K) + #autoLOC_DF_00165 = 休眠室能够保持冷冻小绿人的最低温度(开尔文)。 + #autoLOC_DF_00166 = 休眠室能够保持冷冻小绿人的最高温度(K) + #autoLOC_DF_00167 = 用于冷冻小绿人s的最高温度(开尔文)。 + #autoLOC_DF_00168 = 每个小绿人产生的热量(kW/min) + #autoLOC_DF_00169 = 设备每分钟冷冻一个小绿人所产生的热量(kW)。 + #autoLOC_DF_00170 = 产生热量的冷冻过程(kW) + #autoLOC_DF_00171 = 每次解冻/冷冻过程产生的热量(kW) + #autoLOC_DF_00172 = 以开尔文表示零件温度 + #autoLOC_DF_00173 = 如果在部件上右键单击将显示温度(开尔文),\n如果关闭将显示Celcius + #autoLOC_DF_00174 = 深度冻结杂项。 + #autoLOC_DF_00175 = 休眠室灯亮着 + #autoLOC_DF_00176 = 如果不希望内部\n冷冻室带灯工作,请关闭 + #autoLOC_DF_00177 = 工具提示打开 + #autoLOC_DF_00178 = 打开和关闭工具提示。 + #autoLOC_DF_00179 = 编辑器过滤器 + #autoLOC_DF_00180 = 打开和关闭深度冻结编辑器过滤器类别。 + #autoLOC_DF_00181 = 使用原版应用程序启动图标 + #autoLOC_DF_00182 = 如果打开,将使用原版应用程序启动器,如果关闭,将使用Blizzy工具栏。 + #autoLOC_DF_00183 = 额外调试日志 + #autoLOC_DF_00184 = 把这个打开可以在KSP日志中捕获大量的额外信息来获得一个问题。 + + #autoLOC_DF_00185 = CRY-0300 低温休眠机 + #autoLOC_DF_00186 = REPOSoftTech + #autoLOC_DF_00187 = 设计用于长期储存1个小绿人。 CRY-0300使用糖醇和电量来休眠或唤醒一个小绿人。 请确保你的载具有足够的电量。CRY-0300 配备有10单位的甘醇。警告:CRY-0300每分钟还需要电,以保证它的监控系统正常运转。如果它没有电力维持,就有可能会存在冻死小绿人的危险(小绿人保护协会监督)。 + #autoLOC_DF_00188 = 低温休眠机 + #autoLOC_DF_00189 = CRY-0300R 低温休眠机 + #autoLOC_DF_00190 = 设计用于长期储存1个小绿人。 CRY-0300R使用糖醇和电量来休眠或唤醒一个小绿人。 请确保你的载具有足够的电量。CRY-0300R 配备有10单位的甘醇。警告:CRY-0300R每分钟还需要电,以保证它的监控系统正常运转。如果它没有电力维持,就有可能会存在冻死小绿人的危险(小绿人保护协会监督)。 + #autoLOC_DF_00191 = CRY-1300 低温休眠机 + #autoLOC_DF_00192 = 设计用于长期储存3个小绿人。CRY-1300使用糖醇和电量来休眠或唤醒一个小绿人。 请确保你的载具有足够的电量。CRY-1300 配备有15单位的甘醇。警告:CRY-1300每分钟还需要电,以保证它的监控系统正常运转。如果它没有电力维持,就有可能会存在冻死小绿人的危险(小绿人保护协会监督)。 + #autoLOC_DF_00193 = CRY-2300 低温休眠机 + #autoLOC_DF_00194 = 设计用于长期储存10个小绿人。CRY-2300使用糖醇和电量来休眠或唤醒一个小绿人。请确保你的载具有足够的电量。CRY-2300配备有50单位的甘醇。警告:CRY-2300每分钟还需要电,以保证它的监控系统正常运转。如果它没有电力维持,就有可能会存在冻死小绿人的危险(小绿人保护协会监督)。 + #autoLOC_DF_00195 = RS-X20R 糖醇容器 + #autoLOC_DF_00196 = RS-X20R是一个小体积的径向糖醇容器,用于所有的小绿人休眠和唤醒的需要。是由REPOSoftTech的好员工带来的。如果填充了糖醇,保修期无效。 + #autoLOC_DF_00197 = 低温休眠机 + + #autoLOC_DF_00198 = 在低温学、人体工程学和电气设备领域的专家们中REPOSoftTech的小绿人正在努力使所有的太空礼品都保持活力,并使他们的任务获得成功。 + + #autoLOC_DF_00199 = 休眠 <<1>> + #autoLOC_DF_00200 = 唤醒 <<1>> + + #autoLOC_DF_00201 = 卸船处理 + #autoLOC_DF_00202 = 如果启用了深度冻结,将处理卸载船只上的资源。如果禁用它,它就不会追赶和评估游戏。 + #autoLOC_DF_00203 = Beep Sounds On + #autoLOC_DF_00204 = If enabled Beep sounds are heard inside freezer parts with frozen kerbals. + #autoLOC_DF_00205 = Other Sounds On + #autoLOC_DF_00206 = If enabled all other DeepFreeze sounds are heard. + } +} + + +Localization +{ + de-de + { + #autoLOC_DF_00001 = <<1>> hat sich von der Notfall-Auftauung erholt und geht wieder der normalen Arbeit nach. + #autoLOC_DF_00002 = <<1>> wurde wegen eines Notfalls aufgetaut und muss den Dienst für <<2>> Minuten aussetzen. + #autoLOC_DF_00003 = DeepFreeze + #autoLOC_DF_00004 = DeepFreeze Fahrzeug-Umschalter + #autoLOC_DF_00005 = DeepFreeze Wechsel von Fahrzeugschlug fehl + #autoLOC_DF_00006 = DeepFreeze Kerbals + #autoLOC_DF_00007 = DeepFreeze Alarme + #autoLOC_DF_00008 = Schließe Fenster + #autoLOC_DF_00009 = Fahrzeug + #autoLOC_DF_00010 = Fahrzeugname + #autoLOC_DF_00011 = Bauteil + #autoLOC_DF_00012 = Name des Bauteil + #autoLOC_DF_00013 = Tmp + #autoLOC_DF_00014 = Bauteil Temperatur Status + #autoLOC_DF_00015 = EL + #autoLOC_DF_00016 = Elektrischer Strom Status + #autoLOC_DF_00017 = R.T + #autoLOC_DF_00018 = Remote Tech Status + #autoLOC_DF_00019 = Alarme + #autoLOC_DF_00020 = Drücke den Button für Alarme von Kerbal Alarm Clock die diesem Bauteil zugewiesen sind + #autoLOC_DF_00021 = Letztes Upd + #autoLOC_DF_00022 = Die Zeit seit dem letzten Update des Bauteils + #autoLOC_DF_00023 = Verb. Zeit + #autoLOC_DF_00024 = Ungefähre Zeit, die verbleibt, bis der elektrische Strom erschöpft ist. + #autoLOC_DF_00025 = Fahrzeug <<1>> überhitzt sich. + #autoLOC_DF_00026 = AUS + #autoLOC_DF_00027 = S/BY + #autoLOC_DF_00028 = LEER + #autoLOC_DF_00029 = Fahrzeug <<1>> hat keinen elektrischen Strom mehr.\n Situation kritisch. + #autoLOC_DF_00030 = ALRM + #autoLOC_DF_00031 = Fahrzeug <<1>> hat fast keine elektrische Ladung mehr. + #autoLOC_DF_00032 = NIEDRIG + #autoLOC_DF_00033 = OK + #autoLOC_DF_00034 = NC + #autoLOC_DF_00035 = Alarm + #autoLOC_DF_00036 = Gehe zu Alarme + #autoLOC_DF_00037 = Es gibt momentan keine gefrorenen Kerbals. + #autoLOC_DF_00038 = Kerbal Name + #autoLOC_DF_00039 = Beruf + #autoLOC_DF_00040 = Auftauen + #autoLOC_DF_00041 = Taue diesen Kerbal auf. + #autoLOC_DF_00042 = Kann <<1>> nicht vom KWZ auftauen. Sein Fahrzeug ist noch <<2>> im Einfluss von <<3>> + #autoLOC_DF_00043 = Einfrieren + #autoLOC_DF_00044 = Friere diesen Kerbal ein. + #autoLOC_DF_00045 = KAC Alarme + #autoLOC_DF_00046 = Ändere Fenstergröße + #autoLOC_DF_00047 = <<1>>K + #autoLOC_DF_00048 = <<2>>C + #autoLOC_DF_00049 = <<1>> wurde gefroren beim KWZ gelagert + #autoLOC_DF_00050 = Nicht genügend Funds um <<1>> aufzutauen. + #autoLOC_DF_00051 = <<1>> wurde gefunden und aufgetaut + #autoLOC_DF_00052 = <<1>> wurde gefunden und aufgetaut. Es wurden <<2>> Gelder vom Konto abgezogen + #autoLOC_DF_00053 = Kann <<1>> nicht auftauen. Sein Fahrzeug ist noch <<2>> im Einfluss von <<3>> + + #autoLOC_DF_00054 = Kapazität des Kühlers + #autoLOC_DF_00055 = Gesamtanzahl gefrorener Kerbals + #autoLOC_DF_00056 = Platz im Kühler + #autoLOC_DF_00057 = Ist Bauteil voll? + #autoLOC_DF_00058 = R/T Verbindung + #autoLOC_DF_00059 = Kühler Temp. + #autoLOC_DF_00060 = Kabinentemperatur + #autoLOC_DF_00061 = K + #autoLOC_DF_00062 = DeepFreeze Menü + #autoLOC_DF_00063 = ES pro Kerbal zum Betrieb + #autoLOC_DF_00064 = \u0020p/min + #autoLOC_DF_00065 = Momentaner ES verbrauch + #autoLOC_DF_00066 = \u0020p/sek + #autoLOC_DF_00067 = Glycerin verbr. zum Einfrieren + #autoLOC_DF_00068 = ES pro Kerbal zum Einfrieren/Tauen + #autoLOC_DF_00069 = \nKryokapsel: <<1>> + #autoLOC_DF_00070 = C + #autoLOC_DF_00071 = Kapsel:<<1>> + #autoLOC_DF_00072 = Nicht genügend elektrische Ladung um Kerbals zu überwachen. + #autoLOC_DF_00073 = \u0020Kühler hat kein Energie mehr: Systeme kritisch in <<1>> Sekunden + #autoLOC_DF_00074 = <<1>> starb wegen zu wenig Energie um die Kryotechnik zu betreiben. + #autoLOC_DF_00075 = Prüfe Temperatur, der Kühler wird heiß. + #autoLOC_DF_00076 = Warnung!! UNBEDINGT Temperatur überprüfen. der Kühler wird viel zu heiß. + #autoLOC_DF_00077 = Die Temperatur ist zu hoch, um die Kerbals länger gefroren zu lassen. + #autoLOC_DF_00078 = Überhitzung des Kühlers : System kritisch in <<1>> Sekunden + #autoLOC_DF_00079 = <<1>> starb durch Überhitzung, weil er durch Überhitzung nicht gefroren gehalten werden konnte + #autoLOC_DF_00080 = Überhitzung - Notfall-Auftauung im Gange. + #autoLOC_DF_00081 = Nicht genügen Energie für das Einfrieren des Kerbals + #autoLOC_DF_00082 = \u0020Kryokapsel - Aufladen: <<1>> + #autoLOC_DF_00083 = Nicht genügen Glycerin für das Einfrieren des Kerbals + #autoLOC_DF_00084 = Kann Kerbal nicht einfrieren, wenn die Temperatur mehr als <<1>> beträgt + #autoLOC_DF_00085 = Kann Kerbal nicht einfrieren währen die Besatzung transferiert wird + #autoLOC_DF_00086 = Es kann nicht mehr als ein Kerbal zu Zeit eingefroren werden. + #autoLOC_DF_00087 = RemoteTech entdeckt. Drücke noch einmal "Einfrieren" wenn du den letzten verbleibenden Kerbal einfrieren möchtest + #autoLOC_DF_00088 = Eine aktive Verbindung oder ein aktiver Kerbal wird an Bord benötigt um den Auftau-Prozess einzuleiten + #autoLOC_DF_00089 = Kann Kerbal nicht einfrieren. Der Kühler ist voll + #autoLOC_DF_00090 = Kann Kerbal momentan nicht einfrieren + #autoLOC_DF_00091 = Starte Einfrierprozess + #autoLOC_DF_00092 = Einfrieren abbrechen + #autoLOC_DF_00093 = <<1>> eingefroren + #autoLOC_DF_00094 = Nicht genügend elektrische Ladung zum Auftauen + #autoLOC_DF_00095 = \u0020Kroykapsel - Lade auf:<<1>> + #autoLOC_DF_00096 = Kann <<1>> nicht einfrieren. Das Bauteil ist voll + #autoLOC_DF_00097 = Kann nicht einfrieren, währen die Besatzung transferiert wird + #autoLOC_DF_00098 = Es kann nicht mehr als ein Kerbal gleichzeitig aufgetaut werden + #autoLOC_DF_00099 = Kann Kerbal momentan nicht auftauen + #autoLOC_DF_00100 = Codefehler: Kann Kerbal momentan nicht auftauen, checke das Log + #autoLOC_DF_00101 = Auftauen abgebrochen + #autoLOC_DF_00102 = <<1>> wurde aufgetaut + #autoLOC_DF_00103 = <<1>> wurde aufgetaut, weil es nicht genügend elektrische Ladung gab, im die Kryogenik zu betreiben + #autoLOC_DF_00104 = DeepFreeze mechanisches versagen + #autoLOC_DF_00105 = Fahrzeugwechsel im Gange. Auftauen wird abgebrochen + #autoLOC_DF_00106 = Fahrzeugwechsel im Gange. Einfrieren wird abgebrochen + + #autoLOC_DF_00107 = DeepFreeze Items + #autoLOC_DF_00108 = Es sind weniger als 5 Einheiten Glycerin für die DeepFreeze Kühler an Bord + #autoLOC_DF_00109 = Ein DeepFreeze Alarm wurde ausgelöst. Bitte wechsle zum Ausführen zu <<1>>. + #autoLOC_DF_00110 = DeepFreeze Alarmabwicklung abgeschlossen. + + #autoLOC_DF_00111 = Name + #autoLOC_DF_00112 = Alarm Name + #autoLOC_DF_00113 = Alarm Typ + #autoLOC_DF_00114 = KAC Alarm Typ + #autoLOC_DF_00115 = Zeit verbl. + #autoLOC_DF_00116 = Verbleibende Zeit, bis der Alarm ausgelöst wird + #autoLOC_DF_00117 = Es gibt momentan keine KAC Alarme, die mit einem DeepFreeze Fahrzeug verknüpft sind + #autoLOC_DF_00118 = Löschen + #autoLOC_DF_00119 = Lösche diesen KAC Alarm vollständig + #autoLOC_DF_00120 = Modifizieren + #autoLOC_DF_00121 = Modifiziere diesen Alarm + #autoLOC_DF_00122 = Speichern + #autoLOC_DF_00123 = Speicher Änderungen der Alarme + #autoLOC_DF_00124 = Kann Alarm nicht speichern. Es besteht keine R/Tech Verbindung zum Fahrzeug. + #autoLOC_DF_00125 = DeepFreeze Alarmänderungen gespeichert. + #autoLOC_DF_00126 = DeepFreeze kann Änderung am Alarm nicht speichern. Die Zeit ist abgelaufen. + #autoLOC_DF_00127 = Abbrechen + #autoLOC_DF_00128 = Alle Änderungen abbrechen + #autoLOC_DF_00129 = Name + #autoLOC_DF_00130 = Der Name des Kerbals + #autoLOC_DF_00131 = Merkmal + #autoLOC_DF_00132 = Die Profession des Kerbals + #autoLOC_DF_00133 = Auftauen + #autoLOC_DF_00134 = Taue diesen Kerbal auf, wenn der Alarm aktiviert wird + #autoLOC_DF_00135 = Einfrieren + #autoLOC_DF_00136 = Friere dieser Kerbal ein, wenn der Alarm aktiviert wird + #autoLOC_DF_00137 = Modifizieren + #autoLOC_DF_00138 = Modifiziere die Einstellungen dieses Alarms + + #autoLOC_DF_00139 = Wechsle zu Fahrzeug + #autoLOC_DF_00140 = Nicht jetzt + #autoLOC_DF_00141 = Momentan nicht zum Fahrzeug wechseln + #autoLOC_DF_00142 = Automatischer Wechsel zum Fahrzeug fehlgeschlagen.\nBitte unverzüglich manuell zu dem Fahrzeug wechseln + #autoLOC_DF_00143 = Wechsel zum DeepFreeze Fahrzeug ist notwendig + + #autoLOC_DF_00144 = DeepFreeze Optionen + #autoLOC_DF_00145 = Benötigte elektrische Ladung, um die Kühler zu betreiben + #autoLOC_DF_00146 = Wenn eingeschalten, verbrauchen die Kühler ES zum Laufen + #autoLOC_DF_00147 = Tödliche ES/Hitze Option + #autoLOC_DF_00148 = Wenn diese Option eingeschaltet ist, sterben die Kerbals, wenn es keine ES mehr gibt oder es zu heiß wird + #autoLOC_DF_00149 = Nicht tödliche Zeit im Koma(in Sekunden) + #autoLOC_DF_00150 = Zeit, die ein Kerbal im Koma verbleibt\n wenn die tödliche ES/Hitze Option ausgeschaltet ist + #autoLOC_DF_00151 = Automatische Bergung von gefrorenen Kerbals beim KWZ + #autoLOC_DF_00152 = Wenn aktiviert, werden gefrorene Kerbals beim KWZ automatisch geborgen und die Kosten von den Geldern abgezogen. If on, will AutoRecover Frozen Kerbals at the KWZ \n and deduct the Cost from your funds + #autoLOC_DF_00153 = Kosten um Kerbal beim KWZ aufzutauen + #autoLOC_DF_00154 = Ben. Gelder, um Kerbal beim KZW aufzutauen + #autoLOC_DF_00155 = Ben. Gelder zum Einfrieren/Auftauen von Kerbal + #autoLOC_DF_00156 = Ben. ES zum Einfrieren/Auftauen von Kerbal + #autoLOC_DF_00157 = Ben. Glycerin um einen Kerbal einzufrieren + #autoLOC_DF_00158 = Ben. Glycerin um Kerbal einzufrieren,\nÜberschreibt Werte der Bauteil. + #autoLOC_DF_00159 = DeepFreeze Temperaturen + #autoLOC_DF_00160 = Hol den Taschenrechner raus. + #autoLOC_DF_00161 = Temp. sind in(K)elvin. (K) = (C)elcius + 273.15. (K) = ((F)arenheit + 459.67) × 5/9. Hol' deinen Taschenrechner raus + #autoLOC_DF_00162 = Benötigt regulierte Temperatur + #autoLOC_DF_00163 = Wenn aktiviert, gelten die regulierten Temperaturen Kerbals einzufrieren\nund gefroren zu halten. + #autoLOC_DF_00164 = Min. Temp. für Tiefkühler zum Einfrieren(K) + #autoLOC_DF_00165 = Die minimale Temperatur (in Kelvin) die ein Tiefkühler haben muss,\n um einen Kerbal einzufrieren. + #autoLOC_DF_00166 = Max. Temp. im Kerbals gefroren zu halten(K) + #autoLOC_DF_00167 = Die maximale Temperatur (in Kelvin) für einen Tiefkühler\n um Kerbals gefroren zu halten. + #autoLOC_DF_00168 = Erzeugte Hitze pro Kerbal (kW/min) + #autoLOC_DF_00169 = Menge an thermaler Hitze (kW) die vom Equipment\n für jeden gefroren Kerbal pro Minute erzeugt wird. + #autoLOC_DF_00170 = Erzeugte Hitze durch den Tiefkühlprozess(kW) + #autoLOC_DF_00171 = Menge an thermaler Hitze (kW) die bei jedem Auftauen/Einfrieren erzeugt wird. + #autoLOC_DF_00172 = Zeige Bauteiltemperaturen in Kelvin + #autoLOC_DF_00173 = Wenn aktiviert werden die Temperaturen der Bauteile im Rechtsklick-Menü in Kelvin angezeigt, ansonsten in Celsius. + + #autoLOC_DF_00174 = DeepFreeze Sonst. + #autoLOC_DF_00175 = Tiefkühler Leuchtbänder An + #autoLOC_DF_00176 = Schalte diese Option aus, wenn die internen Leuchtbänder der Tiefkühler nicht leuchten sollen. + #autoLOC_DF_00177 = ToolTips On + #autoLOC_DF_00178 = Stellt die Tooltips an und aus. + #autoLOC_DF_00179 = Editor Filter + #autoLOC_DF_00180 = Schaltet die Filterkategorie für DeepFreeze im Editor an und aus. + #autoLOC_DF_00181 = Nutze Standardicon im Applauncher + #autoLOC_DF_00182 = Wenn aktiviert wird der Standard Anwendungsstarter verwendet\nwenn auf deaktiviert wird die Blizzy Toolbar verwendet, wenn sie installiert ist. + #autoLOC_DF_00183 = Extra Debug Logging + #autoLOC_DF_00184 = Schalte das hier an, um viele zusätzliche Informationen in das Log\nzu schreiben, wenn Du einen Fehler melden willst. + #autoLOC_DF_00185 = CRY-0300 kryonische Tiefkühlkammer + #autoLOC_DF_00186 = REPOSoftTech + #autoLOC_DF_00187 = Entworfen für die Lanzeitlagerung von einem Kerbal. Der CRY-0300 nutzt Glycerin und elektrischen Strom um einen Kerbal einzufrieren oder aufzutauen. Bitte sicherstellen, dass genügend elektrischer Strom im Schiff vorhanden ist. Der CRY-0300 ist mit 10 Einheiten von Glycerin ausgestattet. ACHTUNG: Der CRY-0300 benötigt zudem Elektrischem Strom pro Kerbal pro Minute um seine Überwachungssysteme zu betrieben. Wenn nicht genügend elektrischer Strom vorhanden ist besteht die Gefahr, dass der Kerbal stirbt. + #autoLOC_DF_00188 = deepfreeze kryogen kühler frieren + #autoLOC_DF_00189 = CRY-0300R kryonische Tiefkühlkammer + #autoLOC_DF_00190 = Entworfen für die Lanzeitlagerung von einem Kerbal. Der CRY-0300R nutzt Glycerin und elektrischen Strom um einen Kerbal einzufrieren oder aufzutauen. Bitte sicherstellen, dass genügend elektrischer Strom im Schiff vorhanden ist. Der CRY-0300R ist mit 10 Einheiten von Glycerin ausgestattet. ACHTUNG: Der CRY-0300R benötigt zudem Elektrischem Strom pro Kerbal pro Minute um seine Überwachungssysteme zu betrieben. Wenn nicht genügend elektrischer Strom vorhanden ist besteht die Gefahr, dass der Kerbal stirbt. + #autoLOC_DF_00191 = CRY-1300 kryonische Tiefkühlkammer + #autoLOC_DF_00192 = Entworfen für die Lanzeitlagerung von bis zu 3 Kerbals. Der CRY-1300 nutzt Glycerin und elektrischen Strom um einen Kerbal einzufrieren oder aufzutauen. Bitte sicherstellen, dass genügend elektrischer Strom im Schiff vorhanden ist. Der CRY-1200 ist mit 15 Einheiten von Glycerin ausgestattet. ACHTUNG: Der CRY-1300 benötigt zudem Elektrischem Strom pro Kerbal pro Minute um seine Überwachungssysteme zu betrieben. Wenn nicht genügend elektrischer Strom vorhanden ist besteht die Gefahr, dass gefrorene Kerbals sterben. + #autoLOC_DF_00193 = CRY-2300 kryonische Tiefkühlkammer + #autoLOC_DF_00194 = Entworfen für die Lanzeitlagerung von bis zu 10 Kerbals. Der CRY-2300 nutzt Glycerin und elektrischen Strom um einen Kerbal einzufrieren oder aufzutauen. Bitte sicherstellen, dass genügend elektrischer Strom im Schiff vorhanden ist. Der CRY-1200 ist mit 50 Einheiten von Glycerin ausgestattet. ACHTUNG: Der CRY-0300R benötigt zudem Elektrischem Strom pro Kerbal pro Minute um seine Überwachungssysteme zu betrieben. Wenn nicht genügend elektrischer Strom vorhanden ist besteht die Gefahr, dass gefrorene Kerbals sterben. + #autoLOC_DF_00195 = RS-X20R Glycerin Container + #autoLOC_DF_00196 = The RS-X20R ist ein radialer Glycerin Container mit kleinem Volumen. Es hat Alles, was du zum Einfrieren und Auftauen von Kerbals brauchst. Ein Produkt von den Leuten bei REPOSoftTech. Garantie verfällt, wenn mit Glycerin gefüllt. + #autoLOC_DF_00197 = deepfreeze cryogenic freezer Glycerin tank + + #autoLOC_DF_00198 = Experten in dem Gebiet der Kryogenik, Ergonomik und elektrischen Systemen, die Kerbals von REPOSoftTech tun ihr Bestes um raumfahrende Kerbals am Leben zu halten und ihre Missionen zum Erfolg zu führen. + + #autoLOC_DF_00199 = Friere <<1>> ein + #autoLOC_DF_00200 = Taue <<1>> auf + + #autoLOC_DF_00201 = Unloaded Vessel Processing + #autoLOC_DF_00202 = If enabled DeepFreeze will process resources on unloaded vessels. If disabled, it won't and play the catchup and estimation game. + #autoLOC_DF_00203 = Beep Sounds On + #autoLOC_DF_00204 = If enabled Beep sounds are heard inside freezer parts with frozen kerbals. + #autoLOC_DF_00205 = Other Sounds On + #autoLOC_DF_00206 = If enabled all other DeepFreeze sounds are heard. + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version b/Distribution/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version new file mode 100644 index 0000000..c860933 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version @@ -0,0 +1,9 @@ +{ +"NAME":"DeepFreeze Continued...", +"URL":"http://ksp-avc.cybutek.net/version.php?id=183", +"DOWNLOAD":"http://spacedock.info/mod/142/DeepFreeze%20Continued...", +"VERSION":{"MAJOR":0,"MINOR":31,"PATCH":0,"BUILD":0}, +"KSP_VERSION":{"MAJOR":1,"MINOR":12,"PATCH":0}, +"KSP_VERSION_MIN":{"MAJOR":1,"MINOR":12,"PATCH":0}, +"KSP_VERSION_MAX":{"MAJOR":1,"MINOR":12,"PATCH":99} +} \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFToolTipBox.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFToolTipBox.png new file mode 100644 index 0000000..c6b8f6e Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFToolTipBox.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFbtnRedCross.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFbtnRedCross.png new file mode 100644 index 0000000..a9893c6 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFbtnRedCross.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFbtnResize.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFbtnResize.png new file mode 100644 index 0000000..3f31045 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFbtnResize.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFtoolbar.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFtoolbar.png new file mode 100644 index 0000000..2a89f57 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DFtoolbar.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeEditor.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeEditor.png new file mode 100644 index 0000000..4b11b0b Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeEditor.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeOff.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeOff.png new file mode 100644 index 0000000..f0a30d3 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeOff.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeOn.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeOn.png new file mode 100644 index 0000000..98dc9a7 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeOn.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/Glykerol.png b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/Glykerol.png new file mode 100644 index 0000000..3f9e8ed Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Icons/Glykerol.png differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze.ksp b/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze.ksp new file mode 100644 index 0000000..069bc28 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze.ksp differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/MMDeepFreezeCLS.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/MMDeepFreezeCLS.cfg new file mode 100644 index 0000000..d15783e --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/MMDeepFreezeCLS.cfg @@ -0,0 +1,36 @@ +@PART[CRY-2300Freezer]:HAS[!MODULE[ModuleConnectedLivingSpace]]:NEEDS[ConnectedLivingSpace] +{ + MODULE + { + name = ModuleConnectedLivingSpace + passable = true + } +} + +@PART[CRY-1300Freezer]:HAS[!MODULE[ModuleConnectedLivingSpace]]:NEEDS[ConnectedLivingSpace] +{ + MODULE + { + name = ModuleConnectedLivingSpace + passable = true + } +} + +@PART[CRY-0300Freezer]:HAS[!MODULE[ModuleConnectedLivingSpace]]:NEEDS[ConnectedLivingSpace] +{ + MODULE + { + name = ModuleConnectedLivingSpace + //passable = false + passable = true + } +} +@PART[CRY-0300RFreezer]:HAS[!MODULE[ModuleConnectedLivingSpace]]:NEEDS[ConnectedLivingSpace] +{ + MODULE + { + name = ModuleConnectedLivingSpace + //passable = false + passable = true + } +} \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/MMDeepFreezeCTT.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/MMDeepFreezeCTT.cfg new file mode 100644 index 0000000..95fee85 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/MMDeepFreezeCTT.cfg @@ -0,0 +1,25 @@ +@PART[GlykerolTankRadial]:NEEDS[CommunityTechTree] +{ + @TechRequired = specializedScienceTech +} + +@PART[CRY-0300Freezer]:NEEDS[CommunityTechTree] +{ + @TechRequired = specializedScienceTech +} + +@PART[CRY-0300RFreezer]:NEEDS[CommunityTechTree] +{ + @TechRequired = specializedScienceTech +} + +@PART[CRY-1300Freezer]:NEEDS[CommunityTechTree] +{ + @TechRequired = longTermScienceTech +} + +@PART[CRY-2300Freezer]:NEEDS[CommunityTechTree] +{ + @TechRequired = longTermScienceTech +} + diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300Freezer.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300Freezer.cfg new file mode 100644 index 0000000..55c3dd3 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300Freezer.cfg @@ -0,0 +1,62 @@ +PART +{ + name = CRY-0300Freezer + module = Part + author = JPLRepo + scale = 1 + rescaleFactor = 1 + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/CRY-0300Freezer + texture = CRY0300_color, REPOSoftTech/DeepFreeze/Assets/CRY0300_color + texture = CRY0300_bump, REPOSoftTech/DeepFreeze/Assets/CRY0300_bump + texture = CryopodCushionColor, REPOSoftTech/DeepFreeze/Assets/CryopodCushionColor + } + + node_stack_bottom = 0.0, -0.9133, 0.0, 0.0, -1.0, 0.0, 1 + node_stack_top = 0.0, 0.9181, 0.0, 0.0, 1.0, 0.0, 1 + TechRequired = spaceExploration + entryCost = 8000 + cost = 4000 + category = Utility + subcategory = 0 + //CRY-0300 Cryonic Freezing Chamber + title = #autoLOC_DF_00185 + manufacturer = #autoLOC_DF_00186 + description = #autoLOC_DF_00187 + attachRules = 1,0,1,1,0 + mass = 1.5 + dragModelType = default + maximum_drag = 0.20 + minimum_drag = 0.15 + angularDrag = 2 + crashTolerance = 8 + maxTemp = 2000 // = 3400 + vesselType = Ship + CrewCapacity = 1 + bulkheadProfiles = size1 + tags = #autoLOC_DF_00188 //deepfreeze cryogenic freezer + INTERNAL + { + name = Cry-0300Internals + } + RESOURCE + { + name = Glykerol + amount = 10 + maxAmount = 10 + } + MODULE + { + name = DeepFreezer + FreezerSize = 1 + ChargeRequired = 3000 + GlykerolRequired = 5 + ChargeRate = 30 + FrznChargeRequired = 10 + isPartAnimated = True + PartHasDoor = True + animationName = OpenDoors + cryopodstateclosedstring = True + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RFreezer.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RFreezer.cfg new file mode 100644 index 0000000..6dd7f7d --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RFreezer.cfg @@ -0,0 +1,82 @@ +PART +{ + name = CRY-0300RFreezer + module = Part + author = JPLRepo + //mesh = CRY-0300Freezer.mu + scale = 1 + rescaleFactor = 1 + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/CRY-0300RFreezer + texture = CryopodTexture, REPOSoftTech/DeepFreeze/Assets/CryopodTexture + texture = RadialCryopodTexture, REPOSoftTech/DeepFreeze/Assets/RadialCryopodTexture + } + NODE + { + name = TopNode + transform = TopNode + size = 1 + method = FIXED_JOINT + } + //NODE + //{ + // name = BackNode + // transform = BackNode + // size = 1 + // method = FIXED_JOINT + //} + node_attach = 0.0, 0.0, 0.312, 0.0, 0.0, -1.0 + //node_attach = 0.0, 0.0, 0.452, 0.0, 0.0, -1.0 + //node_stack_top = 0.0, 0.667, 0.0, 0.0, 1.0, 0.0, 0 + TechRequired = spaceExploration + entryCost = 8000 + cost = 4000 + category = Utility + subcategory = 0 + //CRY-0300R Cryonic Freezing Chamber + title = #autoLOC_DF_00189 + manufacturer = #autoLOC_DF_00186 + description = #autoLOC_DF_00190 + attachRules = 1,1,0,1,1 + mass = 0.75 + dragModelType = default + maximum_drag = 0.20 + minimum_drag = 0.15 + angularDrag = 2 + crashTolerance = 8 + maxTemp = 2000 // = 3400 + vesselType = Ship + CrewCapacity = 1 + bulkheadProfiles = size1 + tags = #autoLOC_DF_00188 //deepfreeze cryogenic freezer + + INTERNAL + { + name = Cry-0300RInternals + } + RESOURCE + { + name = Glykerol + amount = 10 + maxAmount = 10 + } + MODULE + { + name = DeepFreezer + FreezerSize = 1 + ChargeRequired = 3000 + GlykerolRequired = 5 + ChargeRate = 30 + FrznChargeRequired = 10 + isPartAnimated = False + isPodExternal = True + PartHasDoor = False + cryopodstateclosedstring = True + } + MODULE + { + name = ModuleCargoPart + packedVolume = -1 + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RPMInternalsMM.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RPMInternalsMM.cfg new file mode 100644 index 0000000..e6daba9 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RPMInternalsMM.cfg @@ -0,0 +1,7 @@ +@PART[CRY-0300Freezer]:FOR[DeepFreeze]:NEEDS[JSIAdvTransparentPods] +{ + MODULE + { + name = JSIAdvTransparentPod + } +} \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RRPMInternalsMM.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RRPMInternalsMM.cfg new file mode 100644 index 0000000..ce26b1e --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY0300RRPMInternalsMM.cfg @@ -0,0 +1,7 @@ +@PART[CRY-0300RFreezer]:FOR[DeepFreeze]:NEEDS[JSIAdvTransparentPods] +{ + MODULE + { + name = JSIAdvTransparentPod + } +} \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY1300Freezer.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY1300Freezer.cfg new file mode 100644 index 0000000..2ce8d72 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY1300Freezer.cfg @@ -0,0 +1,60 @@ +PART +{ + name = CRY-1300Freezer + module = Part + author = JPLRepo + rescaleFactor = 1 + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/Cry-1300Freezer + texture = model000, REPOSoftTech/DeepFreeze/Assets/model000 + texture = model001_NRM, REPOSoftTech/DeepFreeze/Assets/model001_NRM + } + node_stack_top = 0.0, 0.986899, 0.0, 0.0, 1.0, 0.0, 2 + node_stack_bottom = 0.0, -0.986899, 0.0, 0.0, -1.0, 0.0, 2 + CrewCapacity = 3 + TechRequired = specializedConstruction + entryCost = 12400 + cost = 6000 + category = Utility + subcategory = 0 + //CRY-1300 Cryonic Freezing Chamber + title = #autoLOC_DF_00191 + manufacturer = #autoLOC_DF_00186 + description = #autoLOC_DF_00192 + attachRules = 1,0,1,1,0 + mass = 2.5 + dragModelType = default + maximum_drag = 0.2 + minimum_drag = 0.3 + angularDrag = 2 + crashTolerance = 6 + breakingForce = 200 + breakingTorque = 200 + maxTemp = 2000 // = 2900 + vesselType = Ship + bulkheadProfiles = size2 + tags = #autoLOC_DF_00188 //deepfreeze cryogenic freezer + + INTERNAL + { + name = Cry-1300Internals + } + RESOURCE + { + name = Glykerol + amount = 15 + maxAmount = 15 + } + MODULE + { + name = DeepFreezer + FreezerSize = 3 + ChargeRequired = 3000 + GlykerolRequired = 5 + ChargeRate = 30 + FrznChargeRequired = 10 + isPartAnimated = True + cryopodstateclosedstring = True, True, True + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY2300Freezer.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY2300Freezer.cfg new file mode 100644 index 0000000..c13ace2 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/CRY2300Freezer.cfg @@ -0,0 +1,63 @@ +PART +{ + name = CRY-2300Freezer + module = Part + author = ScottPaladin, JPLRepo + rescaleFactor = 1 + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/model + texture = model000, REPOSoftTech/DeepFreeze/Assets/model000 + texture = model001_NRM, REPOSoftTech/DeepFreeze/Assets/model001_NRM + } + node_stack_top = 0.0, 1.830905, 0.0, 0.0, 1.0, 0.0, 2 + node_stack_bottom = 0.0, -1.830905, 0.0, 0.0, -1.0, 0.0, 2 + + CrewCapacity = 10 + TechRequired = advMetalworks + entryCost = 16000 + cost = 8000 + category = Utility + subcategory = 0 + //CRY-2300 Cryonic Freezing Chamber + title = #autoLOC_DF_00193 + manufacturer = #autoLOC_DF_00186 + description = #autoLOC_DF_00194 + attachRules = 1,0,1,1,0 + + mass = 5.25 + dragModelType = default + maximum_drag = 0.2 + minimum_drag = 0.3 + angularDrag = 2 + crashTolerance = 6 + breakingForce = 200 + breakingTorque = 200 + maxTemp = 2900 + + vesselType = Ship + bulkheadProfiles = size2 + tags = #autoLOC_DF_00188 //deepfreeze cryogenic freezer + + INTERNAL + { + name = Cry-2300Internals + } + RESOURCE + { + name = Glykerol + amount = 50 + maxAmount = 50 + } + MODULE + { + name = DeepFreezer + FreezerSize = 10 + ChargeRequired = 3000 + GlykerolRequired = 5 + ChargeRate = 30 + FrznChargeRequired = 10 + isPartAnimated = True + cryopodstateclosedstring = True, True, True, True, True, True, True, True, True, True + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/GlykerolRadialTank.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/GlykerolRadialTank.cfg new file mode 100644 index 0000000..b837777 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Parts/GlykerolRadialTank.cfg @@ -0,0 +1,43 @@ +PART +{ + name = GlykerolTankRadial + module = Part + author = JPLRepo + rescaleFactor = 1 + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/GlykerolRadialTank + texture = GlykerolTank_diff, REPOSoftTech/DeepFreeze/Assets/GlykerolTank_diff + } + node_attach = 0.0, 0.0, -0.12, 0.0, 0.0, -1.0 + TechRequired = specializedConstruction + entryCost = 3000 + cost = 500 + category = FuelTank + subcategory = 0 + //RS-X20R Glykerol Container + title = #autoLOC_DF_00195 + manufacturer = #autoLOC_DF_00186 + description = #autoLOC_DF_00196 + attachRules = 0,1,0,0,1 + mass = 0.03143 + dragModelType = default + maximum_drag = 0.2 + minimum_drag = 0.2 + angularDrag = 2 + crashTolerance = 12 + maxTemp = 2000 // = 2900 + bulkheadProfiles = srf + tags = #autoLOC_DF_00197 //deepfreeze cryogenic freezer glykerol tank + RESOURCE + { + name = Glykerol + amount = 25 + maxAmount = 25 + } + MODULE + { + name = ModuleCargoPart + packedVolume = 100 + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Plugins/PluginData/Config.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Plugins/PluginData/Config.cfg new file mode 100644 index 0000000..5f19013 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Plugins/PluginData/Config.cfg @@ -0,0 +1,36 @@ +DFSettings +{ + DFwindowPosX = 40 + DFwindowPosY = 440 + CFwindowPosX = 450 + CFwindowPosY = 440 + DFKACwindowPosX = 600 + DFKACwindowPosY = 440 + ECreqdForFreezer = False + fatalOption = True + comatoseTime = 300 + UseAppLauncher = True + debugging = False + ToolTips = True + AutoRecoverFznKerbals = True + KSCcostToThawKerbal = 10000 + ECReqdToFreezeThaw = 3000 + GlykerolReqdToFreeze = 5 + RegTempReqd = False + RegTempFreeze = 300 + RegTempMonitor = 400 + heatamtMonitoringFrznKerbals = 100 + heatamtThawFreezeKerbal = 1000 + TempinKelvin = True + defaultTimeoutforCrewXfer = 10 + cryopodResettimeDelay = 2 + DFWindowWidth = 560 + CFWindowWidth = 340 + KACWindowWidth = 485 + ECLowWarningTime = 3600 + EClowCriticalTime = 900 + StripLightsActive = True + internalFrzrCamCode = 100 + internalNxtFrzrCamCode = 47 + internalPrvFrzrCamCode = 98 +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/DoorHandle.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/DoorHandle.cfg new file mode 100644 index 0000000..e611c49 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/DoorHandle.cfg @@ -0,0 +1,70 @@ +PROP +{ + name = DoorHandle + + MODEL + { + model = REPOSoftTech/DeepFreeze/Props/DoorHandle + texture = propBase_DIF, REPOSoftTech/DeepFreeze/Props/propBase_DIF + texture = propBase_EMI, REPOSoftTech/DeepFreeze/Props/propBase_EMI + texture = propLabels_DIF, REPOSoftTech/DeepFreeze/Props/propLabels_DIF + texture = propLabels_EMI, REPOSoftTech/DeepFreeze/Props/propLabels_EMI + } +} +@PROP[DoorHandle]:NEEDS[RasterPropMonitor] +{ + MODULE + { + name = JSIActionGroupSwitch + actionName = plugin + animationName = DOORHandle + animateExterior = false + customSpeed = 0.65 + perPodPersistenceName = extdoorhandle + refreshRate = 60 + switchSound = REPOSoftTech/DeepFreeze/Sounds/externaldoorswitch + switchSoundVolume = 1 + switchTransform = EVAhandle + PLUGINACTION + { + name = DFExtDoorMgr + actionMethod = ButtonExtDoor + stateMethod = ButtonExtDoorState + } + } + MODULE + { + name = JSIActionGroupSwitch + actionName = plugin + colorName = _EmissiveColor + coloredObject = light + disabledColor = 0,255,0,255 + enabledColor = 255,0,0,255 + perPodPersistenceName = extdoorhandle + PLUGINACTION + { + name = DFExtDoorMgr + actionMethod = ButtonExtDoor + stateMethod = ButtonExtDoorState + } + } + MODULE + { + name = JSIActionGroupSwitch + actionName = plugin + colorName = _EmissiveColor + coloredObject = label + disabledColor = 0,255,0,255 + enabledColor = 255,0,0,255 + perPodPersistenceName = extdoorhandle + PLUGINACTION + { + name = DFExtDoorMgr + actionMethod = ButtonExtDoor + stateMethod = ButtonExtDoorState + } + } +} + + + diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/DoorHandle.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/DoorHandle.mu new file mode 100644 index 0000000..6de2e3f Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/DoorHandle.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/ElectricGaugeBar.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/ElectricGaugeBar.cfg new file mode 100644 index 0000000..b511348 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/ElectricGaugeBar.cfg @@ -0,0 +1,65 @@ +PROP +{ + name = DFElectricGaugeBar + + MODEL + { + model = REPOSoftTech/DeepFreeze/Props/flatBarGauge + texture = propBase_DIF, REPOSoftTech/DeepFreeze/Props/propBase_DIF + texture = propBase_EMI, REPOSoftTech/DeepFreeze/Props/propBase_EMI + texture = propLabels_DIF, REPOSoftTech/DeepFreeze/Props/propLabels_DIF + texture = propLabels_EMI, REPOSoftTech/DeepFreeze/Props/propLabels_EMI + } +} +@PROP[DFElectricGaugeBar]:NEEDS[RasterPropMonitor] +{ + MODULE + { + name = JSIVariableAnimator + refreshRate = 2 + VARIABLESET + { + scale = 0,1 + variableName = SYSR_ELECTRICCHARGEPERCENT + controlledTransform = flatBarLit + localScaleStart = 0.02,0.0,0.0 + localScaleEnd = 1,0,0 + } + VARIABLESET + { + scale = 0, 1 + variableName = SYSR_ELECTRICCHARGEPERCENT + coloredObject = flatBarLit + passiveColor = 255,0,0,200 + activeColor = 0,255,0,200 + } + } + + MODULE + { + name = JSISwitchableVariableLabel + labelTransform = gaugeDisplay + fontSize = 0.018 + refreshRate = 3 + switchTransform =COLflatBarSwitch + switchSound = REPOSoftTech/DeepFreeze/Sounds/beep + switchSoundVolume = 1.0 + VARIABLESET + { + labelText = <=0,6:0.0=> $&$ SYSR_ELECTRICCHARGE + } + VARIABLESET + { + labelText = <=0,4:0.0%=> $&$ SYSR_ELECTRICCHARGEPERCENT + } + } + + MODULE + { + name = JSIPropTextureShift + transformToShift = flatBarLabel + layerToShift = _MainTex _Emissive + x = 0.434 + y = 0.716 + } +} \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/GykerolGaugeBar.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/GykerolGaugeBar.cfg new file mode 100644 index 0000000..e4c1cad --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/GykerolGaugeBar.cfg @@ -0,0 +1,65 @@ +PROP +{ + name = DFGlykerolGaugeBar + + MODEL + { + model = REPOSoftTech/DeepFreeze/Props/flatBarGauge + texture = propBase_DIF, REPOSoftTech/DeepFreeze/Props/propBase_DIF + texture = propBase_EMI, REPOSoftTech/DeepFreeze/Props/propBase_EMI + texture = propLabels_DIF, REPOSoftTech/DeepFreeze/Props/propLabels_DIF + texture = propLabels_EMI, REPOSoftTech/DeepFreeze/Props/propLabels_EMI + } +} +@PROP[DFGlykerolGaugeBar]:NEEDS[RasterPropMonitor] +{ + MODULE + { + name = JSIVariableAnimator + refreshRate = 2 + VARIABLESET + { + scale = 0,1 + variableName = SYSR_GLYKEROLPERCENT + controlledTransform = flatBarLit + localScaleStart = 0.02,0.0,0.0 + localScaleEnd = 1,0,0 + } + VARIABLESET + { + scale = 0, 1 + variableName = SYSR_GLYKEROLPERCENT + coloredObject = flatBarLit + passiveColor = 255,0,0,200 + activeColor = 0,255,0,200 + } + } + + MODULE + { + name = JSISwitchableVariableLabel + labelTransform = gaugeDisplay + fontSize = 0.018 + refreshRate = 3 + switchTransform =COLflatBarSwitch + switchSound = REPOSoftTech/DeepFreeze/Sounds/beep + switchSoundVolume = 1.0 + VARIABLESET + { + labelText = <=0,6:0.0=> $&$ SYSR_GLYKEROL + } + VARIABLESET + { + labelText = <=0,4:0.0%=> $&$ SYSR_GLYKEROLPERCENT + } + } + + MODULE + { + name = JSIPropTextureShift + transformToShift = flatBarLabel + layerToShift = _MainTex _Emissive + x = 0.715 + y = 0.447 + } +} \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/LightSwitch.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/LightSwitch.cfg new file mode 100644 index 0000000..ba18391 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/LightSwitch.cfg @@ -0,0 +1,41 @@ +PROP +{ + name = LightSwitch + + MODEL + { + model = REPOSoftTech/DeepFreeze/Props/LightSwitch + texture = propBase_DIF, REPOSoftTech/DeepFreeze/Props/propBase_DIF + texture = propBase_EMI, REPOSoftTech/DeepFreeze/Props/propBase_EMI + } +} +@PROP[LightSwitch]:NEEDS[RasterPropMonitor] +{ + MODULE + { + name = JSIActionGroupSwitch + actionName = intlight + animationName = SwitchOn + animateExterior = False + customSpeed = 2 + initialState = True + internalLightName = InternalLight + perPodPersistenceName = intLightswtch + refreshRate = 60 + switchSound = Squad/Sounds/sound_click_flick + switchTransform = COL_flipSwitch + } + MODULE + { + name = JSIActionGroupSwitch + actionName = intlight + colorName = _EmissiveColor + coloredObject = flipSwitchLight + disabledColor = 0,255,0,255 + enabledColor = 255,0,0,255 + perPodPersistenceName = intLightswtch + } +} + + + diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/LightSwitch.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/LightSwitch.mu new file mode 100644 index 0000000..a846708 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/LightSwitch.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/flatBarGauge.mu b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/flatBarGauge.mu new file mode 100644 index 0000000..59cec66 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/flatBarGauge.mu differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propBase_DIF.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propBase_DIF.dds new file mode 100644 index 0000000..2cdea93 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propBase_DIF.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propBase_EMI.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propBase_EMI.dds new file mode 100644 index 0000000..8c26a5d Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propBase_EMI.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propLabels_DIF.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propLabels_DIF.dds new file mode 100644 index 0000000..109d55b Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propLabels_DIF.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propLabels_EMI.dds b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propLabels_EMI.dds new file mode 100644 index 0000000..944d5f3 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Props/propLabels_EMI.dds differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/beep.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/beep.wav new file mode 100644 index 0000000..eb900c3 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/beep.wav differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/charge_up.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/charge_up.wav new file mode 100644 index 0000000..7f77aa0 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/charge_up.wav differ diff --git a/DeepFreeze/Sounds/ding_ding.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/ding_ding.wav similarity index 100% rename from DeepFreeze/Sounds/ding_ding.wav rename to Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/ding_ding.wav diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/externaldoorswitch.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/externaldoorswitch.wav new file mode 100644 index 0000000..9ff8f36 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/externaldoorswitch.wav differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/flatline.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/flatline.wav new file mode 100644 index 0000000..d9332bd Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/flatline.wav differ diff --git a/DeepFreeze/Sounds/hatch_lock.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/hatch_lock.wav similarity index 100% rename from DeepFreeze/Sounds/hatch_lock.wav rename to Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/hatch_lock.wav diff --git a/DeepFreeze/Sounds/ice_freeze.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/ice_freeze.wav similarity index 100% rename from DeepFreeze/Sounds/ice_freeze.wav rename to Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/ice_freeze.wav diff --git a/DeepFreeze/Sounds/machine_hum.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/machine_hum.wav similarity index 100% rename from DeepFreeze/Sounds/machine_hum.wav rename to Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/machine_hum.wav diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/mon_beep.wav b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/mon_beep.wav new file mode 100644 index 0000000..da84542 Binary files /dev/null and b/Distribution/GameData/REPOSoftTech/DeepFreeze/Sounds/mon_beep.wav differ diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-0300Rinternal.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-0300Rinternal.cfg new file mode 100644 index 0000000..427d0c3 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-0300Rinternal.cfg @@ -0,0 +1,38 @@ +INTERNAL +{ + name = Cry-0300RInternals + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/Cry-0300RInternals + texture = CryopodTexture, REPOSoftTech/DeepFreeze/Assets/CryopodTexture + texture = RadialCryopodTexture, REPOSoftTech/DeepFreeze/Assets/RadialCryopodTexture + } + MODULE + { + name = InternalSeat + seatTransformName = Seat1 + portraitCameraName = Cam1 + allowCrewHelmet = false + } + PROP + { + name = LightSwitch + position = -0.2714,0.1222,-0.045 + rotation = 0.6927769,0.7209744,0.01291895,-0.00944356 + scale = 1,0.9999998,1 + } + PROP + { + name = DFElectricGaugeBar + position = -0.2877,0.04359996,-0.0579 + rotation = -0.507728,-0.4664451,-0.5165215,-0.5077864 + scale = 0.9999998,0.9999998,1 + } + PROP + { + name = DFGlykerolGaugeBar + position = -0.2899,0.04209995,-0.0103 + rotation = 0.4810322,0.4739458,0.5363787,0.5062423 + scale = 0.9999998,0.9999998,1 + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-0300internal.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-0300internal.cfg new file mode 100644 index 0000000..9a6f0c1 --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-0300internal.cfg @@ -0,0 +1,50 @@ +INTERNAL +{ + name = Cry-0300Internals + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/Cry-0300Internals + texture = CryopodCushionColor, REPOSoftTech/DeepFreeze/Assets/CryopodCushionColor + texture = CryopodTexture, REPOSoftTech/DeepFreeze/Assets/CryopodTexture + texture = hitchhikerIVAcolor, REPOSoftTech/DeepFreeze/Assets/hitchhikerIVAcolor + texture = tubesColor, REPOSoftTech/DeepFreeze/Assets/tubesColor + texture = TubesBump, REPOSoftTech/DeepFreeze/Assets/TubesBump + texture = CRY0300_color, REPOSoftTech/DeepFreeze/Assets/CRY0300_color + texture = CRY0300_bump, REPOSoftTech/DeepFreeze/Assets/CRY0300_bump + } + MODULE + { + name = InternalSeat + seatTransformName = Seat1 + portraitCameraName = Cam1 + allowCrewHelmet = true + } + PROP + { + name = DFElectricGaugeBar + position = 0.5166,0.0727,-0.2474 + rotation = -0.5216822,0.4732883,0.4672061,-0.5343822 + scale = 1,1,0.9999999 + } + PROP + { + name = DoorHandle + position = 0.4959,0.106,-0.3206 + rotation = 0.5217043,-0.4824761,-0.4585007,0.533684 + scale = 0.431219,0.4294464,0.5584567 + } + PROP + { + name = LightSwitch + position = 0.5099678,0.04989908,-0.3211304 + rotation = 0.7395766,-0.6729271,0.007982496,0.01148597 + scale = 1,0.9999999,1 + } + PROP + { + name = DFGlykerolGaugeBar + position = 0.5169,0.0736,-0.1979 + rotation = -0.5216822,0.4732883,0.4672061,-0.5343822 + scale = 1,0.9999999,0.9999998 + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-1300internal.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-1300internal.cfg new file mode 100644 index 0000000..fa9cd8f --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-1300internal.cfg @@ -0,0 +1,75 @@ +INTERNAL +{ + name = Cry-1300Internals + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/Cry-1300Internals + texture = CryopodTexture, REPOSoftTech/DeepFreeze/Assets/CryopodTexture + texture = hitchhikerIVAcolor, REPOSoftTech/DeepFreeze/Assets/hitchhikerIVAcolor + texture = tubesColor, REPOSoftTech/DeepFreeze/Assets/tubesColor + texture = TubesBump, REPOSoftTech/DeepFreeze/Assets/TubesBump + texture = CRY2300IVA_color, REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_color + texture = CRY2300IVA_bump, REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_bump + texture = wallTextureColor, REPOSoftTech/DeepFreeze/Assets/wallTextureColor + texture = wallTextureBump, REPOSoftTech/DeepFreeze/Assets/wallTextureBump + texture = cornerColor, REPOSoftTech/DeepFreeze/Assets/cornerColor + texture = cornerBump, REPOSoftTech/DeepFreeze/Assets/cornerBump + } + MODULE + { + name = InternalSeat + seatTransformName = Seat1 + portraitCameraName = Cam1 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat2 + portraitCameraName = Cam2 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat3 + portraitCameraName = Cam3 + allowCrewHelmet = false + } + + PROP + { + name = LightSwitch + position = 0.401,1.024,-0.0459 + rotation = 1,0,0,0 + scale = 1,1,1 + } + PROP + { + name = LightSwitch + position = 0.8220006,-0.02621984,-0.8329241 + rotation = -0.005098441,0.7094415,0.7047272,-0.005132549 + scale = 1,1,1 + } + PROP + { + name = DFGlykerolGaugeBar + position = 0.7593,0.4118,-0.2264 + rotation = 0.6979921,2.147321E-05,-0.7160954,-0.003798927 + scale = 1,0.9999999,1 + } + PROP + { + name = DFElectricGaugeBar + position = 0.759,0.3587,-0.2267 + rotation = 0.6979921,2.147321E-05,-0.7160954,-0.003798927 + scale = 1,0.9999998,1 + } + PROP + { + name = LightSwitch + position = -0.8247,0.0177,0.7968 + rotation = 0.7170615,0.05715754,0.09327104,-0.6883723 + scale = 0.9999999,0.9999996,0.9999999 + } +} diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-2300internal.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-2300internal.cfg new file mode 100644 index 0000000..322ec8e --- /dev/null +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Spaces/Cry-2300internal.cfg @@ -0,0 +1,142 @@ +INTERNAL +{ + name = Cry-2300Internals + MODEL + { + model = REPOSoftTech/DeepFreeze/Assets/Cry-2300Internals + texture = CryopodTexture, REPOSoftTech/DeepFreeze/Assets/CryopodTexture + texture = tubesColor, REPOSoftTech/DeepFreeze/Assets/tubesColor + texture = TubesBump, REPOSoftTech/DeepFreeze/Assets/TubesBump + texture = CRY2300IVA_color, REPOSoftTech/DeepFreeze/Assets/CRY2300IVA_color + texture = wallTextureColor, REPOSoftTech/DeepFreeze/Assets/wallTextureColor + texture = wallTextureBump, REPOSoftTech/DeepFreeze/Assets/wallTextureBump + texture = cornerColor, REPOSoftTech/DeepFreeze/Assets/cornerColor + texture = cornerBump, REPOSoftTech/DeepFreeze/Assets/cornerBump + } + MODULE + { + name = InternalSeat + seatTransformName = Seat1 + portraitCameraName = Cam1 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat2 + portraitCameraName = Cam2 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat3 + portraitCameraName = Cam3 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat4 + portraitCameraName = Cam4 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat5 + portraitCameraName = Cam5 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat6 + portraitCameraName = Cam6 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat7 + portraitCameraName = Cam7 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat8 + portraitCameraName = Cam8 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat9 + portraitCameraName = Cam9 + allowCrewHelmet = false + } + MODULE + { + name = InternalSeat + seatTransformName = Seat10 + portraitCameraName = Cam10 + allowCrewHelmet = false + } + PROP + { + name = LightSwitch + position = -0.4491968,0.7688825,1.412193 + rotation = -0.001290483,-0.01284161,0.9626918,-0.2702923 + scale = 1,1,1 + } + PROP + { + name = LightSwitch + position = 0.4461411,0.7705338,1.41338 + rotation = 0.002996876,-0.05701889,0.9529656,0.2976517 + scale = 0.9999999,0.9999998,1 + } + PROP + { + name = LightSwitch + position = -0.4536696,-0.7662032,1.415538 + rotation = 0.003559022,-0.001952527,-0.3364213,0.9417028 + scale = 0.9999999,0.9999996,0.9999996 + } + PROP + { + name = LightSwitch + position = 0.4545701,-0.7638149,1.428377 + rotation = -0.05827512,-0.01121568,0.2606763,0.9636006 + scale = 0.9999994,0.9999995,1 + } + PROP + { + name = LightSwitch + position = 0.4429578,-0.7722859,-1.43022 + rotation = -0.2621991,0.9643326,0.03320558,-0.0145509 + scale = 0.9999999,1,1 + } + PROP + { + name = LightSwitch + position = -0.4498053,-0.7686884,-1.434795 + rotation = 0.3269992,0.9449015,0.01339657,0.007299995 + scale = 0.9999997,0.9999999,0.9999998 + } + PROP + { + name = LightSwitch + position = 0.4478378,0.7696369,-1.436383 + rotation = 0.9613102,-0.2711986,-0.007622658,0.04770696 + scale = 0.9999996,1,0.9999995 + } + PROP + { + name = LightSwitch + position = -0.4500053,0.7692087,-1.43543 + rotation = 0.953236,0.2990842,0.002567277,0.04339554 + scale = 0.9999996,1,1 + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1c821c9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The Createive Commons Attribution-NonCommercial-ShareAlike 4.0 International license (CC BY-NC-SA 4.0) + +Copyright (c) 2015 JPLRepo + +You are free to: + Share — copy and redistribute the material in any medium or format + Adapt — remix, transform, and build upon the material + The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. + NonCommercial — You may not use the material for commercial purposes. + ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. + No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. + +Notices: + You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. + No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. + +Human Readable license: https://creativecommons.org/licenses/by-nc-sa/4.0/ +Legalcode: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode + diff --git a/README.md b/README.md index bd70848..5a188fe 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,19 @@ DeepFreeze ========== -This is a Kerbal Space Program mod intended to allow players to remove a kerbal from being affected by other mods such as Life Support Mods, Acheivement mods or Fitness Mods. +This is a Kerbal Space Program mod intended to allow players to remove a kerbal from being affected +by other mods such as Life Support Mods, Acheivement mods or Fitness Mods. +This is a forked version from ScottPalandin, who has given his blessing for me to continue development of DeepFreeze on this fork as he does not have the time to continue his work on the mod himself. +His original code can be found in the link below and was licensed as per below, +as such this forked version continues to be licensed the same. +https://github.com/ScottPaladin/DeepFreeze + +Refer to the KSP forum thread or the wiki here on GitHub for information. +For support please refer to the KSP forum thread and raise an issue here on GitHub. + +Source code for Background resources and other utilities that this mod uses can be found here: +https://github.com/JPLRepo/REPOSoftTechKSPUtils License ========== @@ -10,8 +21,17 @@ DeepFreeze is licensed under a Creative Commons 4.0 Share-Alike Attribution Non- Attribution ========== -Sound files remixed from the following sources: -Tymaue - https://www.freesound.org/people/tymaue/sounds/79719/ -KomradeJack - https://www.freesound.org/people/KomradeJack/sounds/213578/ -AlaskaRobotics - https://www.freesound.org/people/AlaskaRobotics/sounds/221566/ -JohnsonBrandediting - https://www.freesound.org/people/JohnsonBrandEditing/sounds/173932/ \ No newline at end of file +Sound files remixed from the following sources: +Tymaue - https://www.freesound.org/people/tymaue/sounds/79719/ +KomradeJack - https://www.freesound.org/people/KomradeJack/sounds/213578/ +AlaskaRobotics - https://www.freesound.org/people/AlaskaRobotics/sounds/221566/ +JohnsonBrandediting - https://www.freesound.org/people/JohnsonBrandEditing/sounds/173932/ +Oddworld - https://www.freesound.org/people/Odd...sounds/171246/ +Benboncan - http://www.freesound.org/people/Benboncan/sounds/61792/ +Halleck -http://www.freesound.org/people/Halleck/sounds/19485/ +user nli2work on KSP forum - Internal Props - door handle, light switch, EC monitoring button, Glykerol monitoring button. + +Mod Contributors: +=========== +JPLRepo - Plugin design and development, C# coding, Implementation and releases. +MerlinsMaster - Graphic design, 3D Models, textures. diff --git a/REPOSoftTechUtils/.gitattributes b/REPOSoftTechUtils/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/REPOSoftTechUtils/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/REPOSoftTechUtils/AppLauncherToolBarExtension.cs b/REPOSoftTechUtils/AppLauncherToolBarExtension.cs new file mode 100644 index 0000000..636f407 --- /dev/null +++ b/REPOSoftTechUtils/AppLauncherToolBarExtension.cs @@ -0,0 +1,355 @@ +/* + * AppLauncherToolBar.cs + * (C) Copyright 2016, Jamie Leighton (JPLRepo) + * REPOSoft Technologies + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of RST Utils. My attempt at creating my own KSP Mod base Architecture. + * + * RST Utils is free software: you can redistribute it and/or modify + * it under the terms of the MIT License + * + * RST Utils is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the MIT License + * along with RST Utils. If not, see . + * + */ +using System; +using KSP.UI.Screens; +using UnityEngine; + +namespace RSTUtils +{ + public class AppLauncherToolBar + { + public static AppLauncherToolBar Instance { get; private set; } + + private bool usingToolbar = false; //Set to true if user is using ToolBar + private IButton button1; //ToolBar button + private string toolBarName; //set to Name for button on ToolBar (modname) + private string toolBarToolTip; // set tooltip for ToolBar button + private string toolBarTexturePath; //The TooBar formatted Texture Path + private GameScenesVisibility toolBarGameScenes; //GameScenes toolbar button can be seen in + + private bool usingStock = false; //Set to true if user is using Stock AppLauncher + private ApplicationLauncherButton stockToolbarButton; // Stock Toolbar Button + private ApplicationLauncher.AppScenes VisibleinScenes; //What scenes is the applauncher button seen in + private UnityEngine.Texture appbtnTexON; //Texture for AppLauncher button when ON + private UnityEngine.Texture appbtnTexOFF; //Texture for AppLauncher button when OFF + private bool showHoverText = false; //Whether to show AppLauncher Hover Text or not. + + private bool _gamePaused; + public Boolean gamePaused + { + get { return _gamePaused; } + private set + { + _gamePaused = value; //Set the private variable + } + } + + private bool _hideUI; + public Boolean hideUI + { + get { return _hideUI; } + private set + { + _hideUI = value; //Set the private variable + } + } + + public bool StockButtonNotNull + { + get { return stockToolbarButton != null; } + } + + public bool ToolBarButtonNotNull + { + get { return button1 != null; } + } + + public bool usingToolBar + { + get { return usingToolbar; } + } + + public bool usingAppLauncher + { + get { return usingStock; } + } + + //GuiVisibility + private bool _Visible; + public Boolean GuiVisible + { + get { return _Visible; } + set + { + _Visible = value; //Set the private variable + } + } + + public bool ShowHoverText + { + get { return showHoverText; } + } + + private void GamePaused() + { + gamePaused = true; + } + + private void GameUnPaused() + { + gamePaused = false; + } + + private void onHideUI() + { + hideUI = true; + } + + private void onShowUI() + { + hideUI = false; + } + /// + /// Constructor for AppLauncherToolBar. You need to construct one of these for your Mod Menu/GUI environment. + /// + /// A string passed into ToolBar indicating the Name of the Mod + /// A string passed into ToolBar to use for the Icon ToolTip + /// A string in ToolBar expected format of the TexturePath for the ToolBarIcon + /// ApplicationLauncher.AppScenes list - logically OR'd + /// Texture reference for the AppLauncher ON Icon + /// Texture reference for the AppLauncher OFF Icon + /// A list of GameScenes use for ToolBar icon visiblity + public AppLauncherToolBar(string toolBarName, string toolBarToolTip, string toolBarTexturePath, + ApplicationLauncher.AppScenes VisibleinScenes, UnityEngine.Texture appbtnTexON, UnityEngine.Texture appbtnTexOFF, params GameScenes[] gameScenes) + { + Instance = this; + if (ToolbarManager.ToolbarAvailable) + { + this.toolBarName = toolBarName; + this.toolBarToolTip = toolBarToolTip; + this.toolBarTexturePath = toolBarTexturePath; + this.toolBarGameScenes = new GameScenesVisibility(gameScenes); + } + this.VisibleinScenes = VisibleinScenes; + this.appbtnTexON = appbtnTexON; + this.appbtnTexOFF = appbtnTexOFF; + } + + private void OnGUIAppLauncherReady() + { + Utilities.Log_Debug("OnGUIAppLauncherReady"); + if (ApplicationLauncher.Ready) + { + Utilities.Log_Debug("Adding AppLauncherButton"); + stockToolbarButton = ApplicationLauncher.Instance.AddModApplication( + onAppLaunchToggle, + onAppLaunchToggle, + onHoverOn, + onHoverOff, + DummyVoid, + DummyVoid, + VisibleinScenes, + appbtnTexOFF); + } + } + + private void DummyVoid() + { + } + + private void onHoverOn() + { + showHoverText = true; + } + private void onHoverOff() + { + showHoverText = false; + } + + public void onAppLaunchToggle() + { + GuiVisible = !GuiVisible; + if (stockToolbarButton != null) + { + stockToolbarButton.SetTexture(GuiVisible ? appbtnTexON : appbtnTexOFF); + } + } + + private void DestroyToolBar() + { + if (ToolbarManager.ToolbarAvailable) + { + if (button1 != null) + button1.Destroy(); + } + } + + private void CreateToolBar() + { + if (ToolbarManager.ToolbarAvailable) + { + button1 = ToolbarManager.Instance.add(toolBarName, "button1"); + button1.TexturePath = toolBarTexturePath; + button1.ToolTip = toolBarToolTip; + button1.Visibility = toolBarGameScenes; + button1.OnClick += e => GuiVisible = !GuiVisible; + } + } + + private void DestroyStockButton() + { + GameEvents.onGUIApplicationLauncherReady.Remove(OnGUIAppLauncherReady); + if (stockToolbarButton != null) + { + ApplicationLauncher.Instance.RemoveModApplication(stockToolbarButton); + stockToolbarButton = null; + } + } + + private void CreateStockButton() + { + Utilities.Log_Debug("Adding onGUIAppLauncher callbacks"); + if (ApplicationLauncher.Ready) + { + if (stockToolbarButton == null) + OnGUIAppLauncherReady(); + } + else + GameEvents.onGUIApplicationLauncherReady.Add(OnGUIAppLauncherReady); + } + + private void OnGameSceneLoadRequestedForAppLauncher(GameScenes SceneToLoad) + { + if (stockToolbarButton != null) + { + ApplicationLauncherButton[] lstButtons = UnityEngine.Object.FindObjectsOfType(); + Utilities.Log_Debug("TSTMenu AppLauncher: Destroying Button-Button Count:" + lstButtons.Length); + ApplicationLauncher.Instance.RemoveModApplication(stockToolbarButton); + stockToolbarButton = null; + } + } + + /// + /// This Class is not using MonoBehaviour but has a Start Method that must be called. + /// Call this in your Start Method for a Mod GUI/Menu Class. + /// + /// True if we are to use the Stock Applauncher, False to use ToolBar mod + public void Start(bool stock) + { + DestroyToolBar(); + if (ToolbarManager.ToolbarAvailable && !stock) + { + // Set up ToolBar button + CreateToolBar(); + usingToolbar = true; + usingStock = false; + } + else + { + // Set up the stock toolbar + CreateStockButton(); + usingToolbar = false; + usingStock = true; + } + GameEvents.onGameSceneLoadRequested.Add(OnGameSceneLoadRequestedForAppLauncher); + GameEvents.onGamePause.Add(GamePaused); + GameEvents.onGameUnpause.Add(GameUnPaused); + GameEvents.onHideUI.Add(onHideUI); + GameEvents.onShowUI.Add(onShowUI); + } + + /// + /// This Class is not using MonoBehaviour but has a Destroy Method that must be called. + /// Call this in your OnDestroy Method for a Mod GUI/Menu Class. + /// + public void Destroy() + { + DestroyToolBar(); + + // Stock toolbar + Utilities.Log_Debug("Removing onGUIAppLauncher callbacks"); + + DestroyStockButton(); + + if (GuiVisible) GuiVisible = !GuiVisible; + GameEvents.onGameSceneLoadRequested.Remove(OnGameSceneLoadRequestedForAppLauncher); + GameEvents.onGamePause.Remove(GamePaused); + GameEvents.onGameUnpause.Remove(GameUnPaused); + GameEvents.onHideUI.Remove(onHideUI); + GameEvents.onShowUI.Remove(onShowUI); + } + + /// + /// Sets the ToolBar Icon visible or not. To be extended in future to not require calling from Mod. + /// Currently it is because I haven't incorporated the mod's Setting for Whether the user wants to use Stock AppLauncher or Toolbar. + /// + /// True if set to visible, false will turn it off + public void setToolBarBtnVisibility(bool visible) + { + button1.Visible = visible; + } + + /// + /// Sets the Applauncher Icon visible or not. To be extended in future to not require calling from Mod. + /// Currently it is because I haven't incorporated the mod's Setting for Whether the user wants to use Stock AppLauncher or Toolbar. + /// + /// True if set to visible, false will turn it off + public void setAppLSceneVisibility(ApplicationLauncher.AppScenes visibleinScenes) + { + VisibleinScenes = visibleinScenes; + stockToolbarButton.VisibleInScenes = VisibleinScenes; + } + + /// + /// Call this to change from AppLauncher to Toobar or vice-versa. + /// Will Destroy ToolBar or AppLauncher Icon and create a new one. + /// + /// True if using AppLauncher, False if using ToolBar + public void chgAppIconStockToolBar(bool stock) + { + if (!stock && ToolbarManager.ToolbarAvailable) + { + DestroyStockButton(); + DestroyToolBar(); + CreateToolBar(); + usingToolbar = true; + usingStock = false; + + } + else + { + DestroyToolBar(); + DestroyStockButton(); + CreateStockButton(); + usingToolbar = false; + usingStock = true; + } + } + + /// + /// Change the ToolBar TexturePath - to say change the Icon + /// + /// string in ToolBar TexturePath format + public void setToolBarTexturePath(string icontoSet) + { + button1.TexturePath = icontoSet; + } + + /// + /// Change the AppLauncher Icon Texture - to say change the Icon + /// + /// Texture to set Icon to + public void setAppLauncherTexture(Texture icontoSet) + { + stockToolbarButton.SetTexture(icontoSet); + } + } +} diff --git a/REPOSoftTechUtils/LICENSE b/REPOSoftTechUtils/LICENSE new file mode 100644 index 0000000..1c821c9 --- /dev/null +++ b/REPOSoftTechUtils/LICENSE @@ -0,0 +1,22 @@ +The Createive Commons Attribution-NonCommercial-ShareAlike 4.0 International license (CC BY-NC-SA 4.0) + +Copyright (c) 2015 JPLRepo + +You are free to: + Share — copy and redistribute the material in any medium or format + Adapt — remix, transform, and build upon the material + The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. + NonCommercial — You may not use the material for commercial purposes. + ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. + No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. + +Notices: + You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. + No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. + +Human Readable license: https://creativecommons.org/licenses/by-nc-sa/4.0/ +Legalcode: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode + diff --git a/REPOSoftTechUtils/README.md b/REPOSoftTechUtils/README.md new file mode 100644 index 0000000..0efade9 --- /dev/null +++ b/REPOSoftTechUtils/README.md @@ -0,0 +1,16 @@ +REPOSoftTech Utilities +====================== + +This is a collection of common software utilities used throughout my Kerbal Space Program mods. + + +For support please refer to the KSP forum thread and raise an issue here on GitHub. + +License +========== +These Utilities are licensed under a Creative Commons 4.0 Share-Alike Attribution Non-Commercial license. + +Mod Contributors: +=========== +JPLRepo - Plugin design and development, C# coding, Implementation and releases. + diff --git a/REPOSoftTechUtils/RSTutilities.cs b/REPOSoftTechUtils/RSTutilities.cs new file mode 100644 index 0000000..a44fafa --- /dev/null +++ b/REPOSoftTechUtils/RSTutilities.cs @@ -0,0 +1,1469 @@ + + +/* + * (C) Copyright 2016, Jamie Leighton (JPLRepo) + * REPOSoft Technologies + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of RST Utils. My attempt at creating my own KSP Mod base Architecture. + * + * RST Utils is free software: you can redistribute it and/or modify + * it under the terms of the MIT License + * + * RST Utils is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the MIT License + * along with RST Utils. If not, see . + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Highlighting; +using UnityEngine; +using Object = UnityEngine.Object; +using Random = System.Random; + +namespace RSTUtils +{ + public enum GameState + { + FLIGHT = 0, + EDITOR = 1, + EVA = 2, + SPACECENTER = 3, + OTHER = 4 + } + + internal static class Utilities + { + public static int randomSeed = new Random().Next(); + private static int _nextrandomInt = randomSeed; + + public static int getnextrandomInt() + { + _nextrandomInt ++; + return _nextrandomInt; + } + + private static GameState state; + + //Set the Game State mode indicator, 0 = inflight, 1 = editor, 2 on EVA or F2 + public static bool GameModeisFlight + { + get + { + state = SetModeFlag(); + if (state == GameState.FLIGHT) return true; + return false; + } + } + + public static bool GameModeisEditor + { + get + { + state = SetModeFlag(); + if (state == GameState.EDITOR) return true; + return false; + } + } + + public static bool GameModeisEVA + { + get + { + state = SetModeFlag(); + if (state == GameState.EVA) return true; + return false; + } + } + + public static bool GameModeisSpaceCenter + { + get + { + state = SetModeFlag(); + if (state == GameState.SPACECENTER) return true; + return false; + } + } + + public static GameState GameMode + { + get + { + return SetModeFlag(); + } + } + + public static GameState SetModeFlag() + { + //Set the mode flag, 0 = inflight, 1 = editor, 2 on EVA or F2 + if (HighLogic.LoadedScene == GameScenes.SPACECENTER) + { + return GameState.SPACECENTER; + } + //if (FlightGlobals.fetch != null && FlightGlobals.ActiveVessel != null) // Check if in flight + if (HighLogic.LoadedSceneIsFlight) + { + if (FlightGlobals.fetch != null) + { + if (FlightGlobals.ActiveVessel != null) + { + if (FlightGlobals.ActiveVessel.isEVA) // EVA kerbal + { + return GameState.EVA; + } + } + } + return GameState.FLIGHT; + } + if (EditorLogic.fetch != null) // Check if in editor + { + return GameState.EDITOR; + } + return GameState.OTHER; + } + + #region GeometryandSpace + //Geometry and space + + public static double DistanceFromHomeWorld(Vessel vessel) + { + Vector3d vslPos = vessel.GetWorldPos3D(); + CelestialBody HmePlanet = Planetarium.fetch.Home; + Log_Debug("Home = " + HmePlanet.name + " Pos = " + HmePlanet.position); + Log_Debug("Vessel Pos = " + vslPos); + Vector3d hmeplntPos = HmePlanet.position; + double DstFrmHome = Math.Sqrt(Math.Pow(vslPos.x - hmeplntPos.x, 2) + Math.Pow(vslPos.y - hmeplntPos.y, 2) + Math.Pow(vslPos.z - hmeplntPos.z, 2)); + Log_Debug("Distance from Home Planet = " + DstFrmHome); + return DstFrmHome; + } + + public static double DistanceFromHomeWorld(string bodyname) + { + CelestialBody body = FlightGlobals.Bodies.FirstOrDefault(a => a.name == bodyname); + if (body == null) body = Planetarium.fetch.Home; + Vector3d bodyPos = body.getPositionAtUT(0); + CelestialBody HmePlanet = Planetarium.fetch.Home; + Log_Debug("Home = " + HmePlanet.name + " Pos = " + HmePlanet.getPositionAtUT(0)); + Log_Debug("Body Pos = " + bodyPos); + Vector3d hmeplntPos = HmePlanet.getPositionAtUT(0); + double DstFrmHome = Math.Sqrt(Math.Pow(bodyPos.x - hmeplntPos.x, 2) + Math.Pow(bodyPos.y - hmeplntPos.y, 2) + Math.Pow(bodyPos.z - hmeplntPos.z, 2)); + Log_Debug("Distance from Home Planet = " + DstFrmHome); + return DstFrmHome; + } + + public static bool CelestialBodyDistancetoSun(CelestialBody cb, out Vector3d sun_dir, out double sun_dist) + { + // bodies traced against + CelestialBody sun = FlightGlobals.Bodies[0]; + if (cb == sun) //If we have passed in the sun as the cb we default to a distance of 700000Km + { + sun_dir = Vector3d.forward; + sun_dist = sun.Radius + 700000000; + sun_dir /= sun_dist; + return true; + } + sun_dir = sun.position - cb.position; + sun_dist = sun_dir.magnitude; + sun_dir /= sun_dist; + sun_dist -= sun.Radius; + return true; + } + + // return sun luminosity + public static double SolarLuminosity + { + get + { + // note: it is 0 before loading first vessel in a game session, we compute it in that case + if (PhysicsGlobals.SolarLuminosity <= double.Epsilon) + { + double A = FlightGlobals.GetHomeBody().orbit.semiMajorAxis; + return A * A * 12.566370614359172 * PhysicsGlobals.SolarLuminosityAtHome; + } + return PhysicsGlobals.SolarLuminosity; + } + } + + #endregion GeometryandSpace + + #region ObjectsandTransforms + public static void PrintTransform(Transform t, string title = "") + { + Log_Debug("------" + title + "------"); + Log_Debug("Position: " + t.localPosition); + Log_Debug("Rotation: " + t.localRotation); + Log_Debug("Scale: " + t.localScale); + Log_Debug("------------------"); + } + + public static void DumpObjectProperties(object o, string title = "---------") + { + // Iterate through all of the properties + Log_Debug("--------- " + title + " ------------"); + foreach (PropertyInfo property in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public)) + { + if (property.CanRead) + Log_Debug(property.Name + " = " + property.GetValue(o, null)); + } + Log_Debug("--------------------------------------"); + } + + // Dump an object by reflection + internal static void DumpObjectFields(object o, string title = "---------") + { + // Dump (by reflection) + Debug.Log("---------" + title + "------------"); + foreach (FieldInfo field in o.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public)) + { + if (!field.IsStatic) + { + Debug.Log(field.Name + " = " + field.GetValue(o)); + } + } + Debug.Log("--------------------------------------"); + } + + // Use Reflection to get a field from an object + internal static object GetObjectField(object o, string fieldName) + { + object outputObj = new object(); + bool foundObj = false; + foreach (FieldInfo field in o.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public)) + { + if (!field.IsStatic) + { + if (field.Name == fieldName) + { + foundObj = true; + outputObj = field.GetValue(o); + break; + } + } + } + if (foundObj) + { + return outputObj; + } + return null; + } + + /** + * Recursively searches for a named transform in the Transform heirarchy. The requirement of + * such a function is sad. This should really be in the Unity3D API. Transform.Find() only + * searches in the immediate children. + * + * @param transform Transform in which is search for named child + * @param name Name of child to find + * + * @return Desired transform or null if it could not be found + */ + + internal static Transform FindInChildren(Transform transform, string name) + { + // Is this null? + if (transform == null) + { + return null; + } + + // Are the names equivalent + if (transform.name == name) + { + return transform; + } + + // If we did not find a transform, search through the children + return (from Transform child in transform select FindInChildren(child, name)).FirstOrDefault(t => t != null); + + // Return the transform (will be null if it was not found) + } + + public static Transform FindChildRecursive(Transform parent, string name) + { + return parent.gameObject.GetComponentsInChildren().FirstOrDefault(t => t.name == name); + } + + public static Animation FindAnimChildRecursive(Transform parent, string name) + { + return parent.gameObject.GetComponentsInChildren().FirstOrDefault(t => t.name == name); + } + + internal static void dmpKerbalRefs(Kerbal kerbal, Kerbal seatkerbalref, Kerbal protocrewkerbalref) + { + if (kerbal != null) + { + Log_Debug("kerbal " + kerbal.name + " " + kerbal.GetInstanceID()); + Log_Debug(kerbal.GetComponent("TRIvaModule") != null + ? "kerbal has TRIvaModule attached" + : "kerbal DOES NOT have TRIvaModule attached"); + } + + if (seatkerbalref != null) + { + Log_Debug("seatkerbalref " + seatkerbalref.name + " " + seatkerbalref.GetInstanceID()); + Log_Debug(seatkerbalref.GetComponent("TRIvaModule") != null + ? "seatkerbalref has TRIvaModule attached" + : "seatkerbalref DOES NOT have TRIvaModule attached"); + } + if (protocrewkerbalref != null) + { + Log_Debug("protocrewkerbalref " + protocrewkerbalref.name + " " + protocrewkerbalref.GetInstanceID()); + Log_Debug(protocrewkerbalref.GetComponent("TRIvaModule") != null + ? "protocrewkerbalref has TRIvaModule attached" + : "protocrewkerbalref DOES NOT have TRIvaModule attached"); + } + } + + internal static void dmpAllKerbals() + { + foreach (Kerbal kerbal in Resources.FindObjectsOfTypeAll()) + { + Log_Debug("Kerbal " + kerbal.name + " " + kerbal.crewMemberName + " instance " + kerbal.GetInstanceID() + " rosterstatus " + kerbal.rosterStatus); + Log_Debug(kerbal.protoCrewMember == null ? "ProtoCrewmember is null " : "ProtoCrewmember exists " + kerbal.protoCrewMember.name); + } + } + + internal static void dmpAnimationNames(Animation anim) + { + List states = new List(anim.Cast()); + Log_Debug("Animation " + anim.name); + foreach (AnimationState state in states) + { + Log_Debug("Animation clip " + state.name); + } + } + + // The following method is modified from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + internal static void setTransparentTransforms(this Part thisPart, string transparentTransforms) + { + string transparentShaderName = "Transparent/Specular"; + var transparentShader = Shader.Find(transparentShaderName); + foreach (string transformName in transparentTransforms.Split('|')) + { + Log_Debug("setTransparentTransforms " + transformName); + try + { + Transform tr = thisPart.FindModelTransform(transformName.Trim()); + if (tr != null) + { + // We both change the shader and backup the original shader so we can undo it later. + Shader backupShader = tr.GetComponent().material.shader; + tr.GetComponent().material.shader = transparentShader; + } + } + catch (Exception e) + { + Debug.Log("Unable to set transparent shader transform " + transformName); + Debug.LogException(e); + } + } + } + + #endregion ObjectsandTransforms + + #region Cameras + + internal static Camera FindCamera(string name) + { + return Camera.allCameras.FirstOrDefault(c => c.name == name); + } + + // Dump all Unity Cameras + internal static void DumpCameras() + { + // Dump (by reflection) + Debug.Log("--------- Dump Unity Cameras ------------"); + foreach (Camera c in Camera.allCameras) + { + Debug.Log("Camera " + c.name + " cullingmask " + c.cullingMask + " depth " + c.depth + " farClipPlane " + c.farClipPlane + " nearClipPlane " + c.nearClipPlane); + } + + Debug.Log("--------------------------------------"); + } + + public static Camera findCameraByName(string camera) + { + return Camera.allCameras.FirstOrDefault(cam => cam.name == camera); + } + + private static Camera StockOverlayCamera; + /// + /// Returns True if the Stock Overlay Camera Mode is on, otherwise will return false. + /// + public static bool StockOverlayCamIsOn + { + get + { + StockOverlayCamera = findCameraByName("InternalSpaceOverlay Host"); + if (StockOverlayCamera != null) return true; + return false; + } + } + + private static Shader DepthMaskShader; + private static string DepthMaskShaderName = "DepthMask"; + /// + /// Will search for and change the Mesh (and all it's children) supplied in MeshName Field on the part supplied to Enabled or NotEnabled based on the SetVisible parm. + /// + /// The part to look for the mesh on + /// True will Enable the mesh, False will disable the mesh + /// String containing the Mesh name to look for on the part + internal static void SetInternalDepthMask(Part part, bool SetVisible, string MeshName = "") + { + if (DepthMaskShader == null) DepthMaskShader = Shader.Find(DepthMaskShaderName); + if (part.internalModel != null) + { + if (MeshName != "") + { + Transform parentTransform = FindInChildren(part.internalModel.transform, MeshName); + if (parentTransform != null) + { + parentTransform.gameObject.SetActive(SetVisible); + } + } + } + } + + #endregion Cameras + + #region Animations + public static IEnumerator WaitForAnimation(Animation animation, string name) + { + do + { + yield return null; + } while (animation.IsPlaying(name)); + } + + public static IEnumerator WaitForAnimationNoClip(Animation animation) + { + do + { + yield return null; + } while (animation.isPlaying); + } + + #endregion Animations + + #region Kerbals + + // The following method is derived from TextureReplacer mod. Which is licensed as: + //Copyright © 2013-2015 Davorin Učakar, Ryan Bray + //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + private static double atmSuitPressure = 50.0; + + internal static bool isAtmBreathable() + { + bool value = !HighLogic.LoadedSceneIsFlight + || (FlightGlobals.getStaticPressure() >= atmSuitPressure); + Log_Debug("isATMBreathable Inflight? " + value + " InFlight " + HighLogic.LoadedSceneIsFlight + " StaticPressure " + FlightGlobals.getStaticPressure()); + return value; + } + + // The following method is derived from TextureReplacer mod. Which is licensed as: + //Copyright © 2013-2015 Davorin Učakar, Ryan Bray + //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + private static Mesh[] helmetMesh = { null, null }; + + private static Mesh[] visorMesh = { null, null }; + private static bool helmetMeshstored; + + internal static void storeHelmetMesh() + { + Log_Debug("StoreHelmetMesh"); + foreach (Kerbal kerbal in Resources.FindObjectsOfTypeAll()) + { + int gender = kerbal.transform.name == "kerbalFemale" ? 1 : 0; + // Save pointer to helmet & visor meshes so helmet removal can restore them. + foreach (SkinnedMeshRenderer smr in kerbal.GetComponentsInChildren(true)) + { + if (smr.name.EndsWith("helmet", StringComparison.Ordinal)) + helmetMesh[gender] = smr.sharedMesh; + else if (smr.name.EndsWith("visor", StringComparison.Ordinal)) + visorMesh[gender] = smr.sharedMesh; + } + } + helmetMeshstored = true; + } + + // The following method is derived from TextureReplacer mod.Which is licensed as: + //Copyright © 2013-2015 Davorin Učakar, Ryan Bray + //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + internal static void setHelmetshaders(Kerbal thatKerbal, bool helmetOn) + { + if (!helmetMeshstored) + storeHelmetMesh(); + + //This will check if Atmospher is breathable then we always remove our hetmets regardless. + if (helmetOn && isAtmBreathable()) + { + helmetOn = false; + Log_Debug("setHelmetShaders to put on helmet but in breathable atmosphere"); + } + + try + { + foreach (SkinnedMeshRenderer smr in thatKerbal.helmetTransform.GetComponentsInChildren()) + { + if (smr.name.EndsWith("helmet", StringComparison.Ordinal)) + smr.sharedMesh = helmetOn ? helmetMesh[(int)thatKerbal.protoCrewMember.gender] : null; + else if (smr.name.EndsWith("visor", StringComparison.Ordinal)) + smr.sharedMesh = helmetOn ? visorMesh[(int)thatKerbal.protoCrewMember.gender] : null; + } + } + catch (Exception ex) + { + Log("Error attempting to setHelmetshaders for " + thatKerbal.name + " to " + helmetOn); + Log(ex.Message); + } + } + + // The following method is derived from TextureReplacer mod. Which is licensed as: + //Copyright © 2013-2015 Davorin Učakar, Ryan Bray + //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + internal static void setHelmets(this Part thisPart, bool helmetOn) + { + if (thisPart.internalModel == null) + { + Log_Debug("setHelmets but no internalModel"); + return; + } + + if (!helmetMeshstored) + storeHelmetMesh(); + + Log_Debug("setHelmets helmetOn=" + helmetOn); + //Kerbal thatKerbal = null; + foreach (InternalSeat thatSeat in thisPart.internalModel.seats) + { + if (thatSeat.crew != null) + { + Kerbal thatKerbal = thatSeat.kerbalRef; + if (thatKerbal != null) + { + thatSeat.allowCrewHelmet = helmetOn; + Log_Debug("Setting helmet=" + helmetOn + " for kerbal " + thatSeat.crew.name); + // `Kerbal.ShowHelmet(false)` irreversibly removes a helmet while + // `Kerbal.ShowHelmet(true)` has no effect at all. We need the following workaround. + // I think this can be done using a coroutine to despawn and spawn the internalseat crewmember kerbalref. + // But I found this workaround in TextureReplacer so easier to use that. + //if (thatKerbal.showHelmet) + //{ + setHelmetshaders(thatKerbal, helmetOn); + //} + //else + // Log_Debug("Showhelmet is OFF so the helmettransform does not exist"); + } + else + Log_Debug("kerbalref = null?"); + } + } + } + + // Sets the kerbal layers to make them visible (Thawed) or not (Frozen), setVisible = true sets layers to visible, false turns them off. + internal static void setFrznKerbalLayer(Part part, ProtoCrewMember kerbal, bool setVisible) + { + if (!setVisible) + { + kerbal.KerbalRef.SetVisibleInPortrait(setVisible); + kerbal.KerbalRef.InPart = null; + } + + kerbal.KerbalRef.gameObject.SetActive(setVisible); + if (setVisible) + { + kerbal.KerbalRef.SetVisibleInPortrait(setVisible); + kerbal.KerbalRef.InPart = part; + } + + } + + private static RuntimeAnimatorController kerbalIVAController, myController; + private static AnimatorOverrideController myOverrideController; + + internal static void subdueIVAKerbalAnimations(Kerbal kerbal) + { + try + { + foreach (Animator anim in kerbal.gameObject.GetComponentsInChildren()) + { + if (anim.name == kerbal.name) + { + kerbalIVAController = anim.runtimeAnimatorController; + myController = anim.runtimeAnimatorController; + myOverrideController = new AnimatorOverrideController(); + myOverrideController.runtimeAnimatorController = myController; + myOverrideController["idle_animA_upWord"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animB"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animC"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animD_dance"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animE_drummingHelmet"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animI_drummingControls"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animJ_yo"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animJ_IdleLoopShort"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["idle_animK_footStretch"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["head_rotation_staringUp"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["head_rotation_longLookUp"] = myOverrideController["idle_animH_notDoingAnything"]; + myOverrideController["head_faceExp_fun_ohAh"] = myOverrideController["idle_animH_notDoingAnything"]; + // Put this line at the end because when you assign a controller on an Animator, unity rebinds all the animated properties + anim.runtimeAnimatorController = myOverrideController; + Log_Debug("Animator " + anim.name + " for " + kerbal.name + " subdued"); + } + } + } + catch (Exception ex) + { + Log(" failed to subdue IVA animations for " + kerbal.name); + Debug.LogException(ex); + } + } + + internal static void reinvigerateIVAKerbalAnimations(Kerbal kerbal) + { + foreach (Animator anim in kerbal.gameObject.GetComponentsInChildren()) + { + if (anim.name == kerbal.name) + { + myController = kerbalIVAController; + myOverrideController = new AnimatorOverrideController(); + myOverrideController.runtimeAnimatorController = myController; + // Put this line at the end because when you assign a controller on an Animator, unity rebinds all the animated properties + anim.runtimeAnimatorController = myOverrideController; + Log_Debug("Animator " + anim.name + " for " + kerbal.name + " reinvigerated"); + } + } + } + + #endregion Kerbals + + #region Vessels + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + /// + /// Returns True if thatVessel is the activevessel and the camera is in IVA mode, otherwise returns false. + /// + /// + /// + internal static bool VesselIsInIVA(Vessel thatVessel) + { + // Inactive IVAs are renderer.enabled = false, this can and should be used... + // ... but now it can't because we're doing transparent pods, so we need a more complicated way to find which pod the player is in. + return HighLogic.LoadedSceneIsFlight && IsActiveVessel(thatVessel) && IsInIVA; + } + + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + /// + /// Returns True if thatVessel is the ActiveVessel, otherwise returns false. + /// + /// + /// + internal static bool IsActiveVessel(Vessel thatVessel) + { + return HighLogic.LoadedSceneIsFlight && thatVessel != null && thatVessel.isActiveVessel; + } + + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + public static bool UserIsInPod(Part thisPart) + { + + // Just in case, check for whether we're not in flight. + if (!HighLogic.LoadedSceneIsFlight) + return false; + + // If we're not in IVA, or the part does not have an instantiated IVA, the user can't be in it. + if (!VesselIsInIVA(thisPart.vessel) || thisPart.internalModel == null) + return false; + + // Now that we got that out of the way, we know that the user is in SOME pod on our ship. We just don't know which. + // Let's see if he's controlling a kerbal in our pod. + if (ActiveKerbalIsLocal(thisPart)) + return true; + + // There still remains an option of InternalCamera which we will now sort out. + if (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal) + { + // So we're watching through an InternalCamera. Which doesn't record which pod we're in anywhere, like with kerbals. + // But we know that if the camera's transform parent is somewhere in our pod, it's us. + // InternalCamera.Instance.transform.parent is the transform the camera is attached to that is on either a prop or the internal itself. + // The problem is figuring out if it's in our pod, or in an identical other pod. + // Unfortunately I don't have anything smarter right now than get a list of all transforms in the internal and cycle through it. + // This is a more annoying computation than looking through every kerbal in a pod (there's only a few of those, + // but potentially hundreds of transforms) and might not even be working as I expect. It needs testing. + return thisPart.internalModel.GetComponentsInChildren().Any(thisTransform => thisTransform == InternalCamera.Instance.transform.parent); + } + + return false; + } + + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + public static bool ActiveKerbalIsLocal(this Part thisPart) + { + return FindCurrentKerbal(thisPart) != null; + } + + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + public static Kerbal FindCurrentKerbal(this Part thisPart) + { + if (thisPart.internalModel == null || !VesselIsInIVA(thisPart.vessel)) + return null; + // InternalCamera instance does not contain a reference to the kerbal it's looking from. + // So we have to search through all of them... + return (from thatSeat in thisPart.internalModel.seats + where thatSeat.kerbalRef != null + where thatSeat.kerbalRef.eyeTransform == InternalCamera.Instance.transform.parent + select thatSeat.kerbalRef).FirstOrDefault(); + } + + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + /// + /// True if Camera is in IVA mode, otherwise false. + /// + internal static bool IsInIVA + { + get { return CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA; } + } + /// + /// True if Camera is in Internal mode, otherwise false. + /// + internal static bool IsInInternal + { + get { return CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal; } + } + + internal static bool ValidVslType(Vessel v) + { + switch (v.vesselType) + { + case VesselType.Base: + case VesselType.Lander: + case VesselType.Probe: + case VesselType.Rover: + case VesselType.Ship: + case VesselType.Station: + return true; + + default: + return false; + } + } + + // The following method is taken from Kerbal Alarm Clock as-is. Which is covered by MIT license. + internal static int getVesselIdx(Vessel vtarget) + { + for (int i = 0; i < FlightGlobals.Vessels.Count; i++) + { + if (FlightGlobals.Vessels[i].id == vtarget.id) + { + Log_Debug("Found Target idx=" + i + " (" + vtarget.id + ")"); + return i; + } + } + return -1; + } + + /// + /// Will Spawn the Internal Model for a part, we do this for DeepFreeze Mod because it doesn't work if the crew capacity is zero, which may be + /// the case sometimes for DeepFreeze parts. + /// + /// The Part to spawn the internal model for + /// True if successful or False if not + internal static bool spawnInternal(Part part) + { + try + { + if (part.internalModel != null) return true; + part.CreateInternalModel(); + if (part.internalModel != null) + { + part.internalModel.Initialize(part); + part.internalModel.SpawnCrew(); + } + else + { + return false; + } + + return true; + } + catch (Exception) + { + return false; + } + } + + + public static void PartHighlight(Part part, bool on) + { + if (on) + { + if (part.HighlightActive) + { + var color = XKCDColors.Yellow; + part.SetHighlightColor(color); + part.SetHighlight(true, false); + } + } + else + { + if (part.HighlightActive) + { + part.SetHighlightDefault(); + part.SetHighlight(false, false); + } + } + } + + #endregion Vessels + + #region Temperature + //Temperature + internal static float KelvintoCelsius(float kelvin) + { + return kelvin - 273.15f; + } + + internal static float CelsiustoKelvin(float celsius) + { + return celsius + 273.15f; + } + + #endregion Temperature + + #region Resources + + /// + /// Can be used to get amount of a resource there is, amount of space for a resource there is, or push/pull resource. + /// + /// this is the vessel + /// this is the string resource name + /// amount of the resource + /// true to push/pull + /// true if pulling false if pushing + /// amount of the resource available or push/pulled + /// max amount of resource vessel can store + /// bool if successful or not + internal static bool requireResource(Vessel craft, string res, double resAmount, bool ConsumeResource, bool pulling, out double resavail, out double maxavail) + { + int resID = PartResourceLibrary.Instance.GetDefinition(res).id; + bool result = requireResourceID(craft, resID, resAmount, ConsumeResource, pulling, out resavail, out maxavail); + return result; + } + + /// + /// Can be used to get amount of a resource there is, amount of space for a resource there is, or push/pull resource. + /// + /// this is the vessel + /// this is the hash of the resource name + /// amount of the resource + /// true to push/pull + /// true if pulling false if pushing + /// amount of the resource available or push/pulled + /// max amount of resource vessel can store + /// bool if successful or not + internal static bool requireResourceID(Vessel craft, int res, double resAmount, bool ConsumeResource, bool pulling, out double resavail, out double maxavail) + { + if (!craft.loaded) + { + resavail = 0; + maxavail = 0; + return false; // Unloaded resource checking is unreliable. + } + double amount, maxamount; + //Get how much of the resource is available and capacity + craft.resourcePartSet.GetConnectedResourceTotals(res, out amount, out maxamount, pulling); + //If we are pulling and the amount avail is less than the amount we want. return what's available but don't take the resource + //If we are not pulling is the amount avail (space available) greater than the amount we want. if not return what's available but don't store it. + //So in both cases amount must be >= the anout we want. + resavail = amount; + maxavail = maxamount; + if (amount < resAmount) + { + return false; + } + //If we are not consuming the resource (or storing) just return how much there is. + if (!ConsumeResource) + { + return true; + } + //Now we push or pull + var amountdrawn = craft.RequestResource(craft.rootPart, res, resAmount, pulling); + if (amountdrawn < resAmount * 0.99) + { + resavail = amountdrawn; + return false; + } + resavail = amountdrawn; + return true; + } + + /// + /// Converts Stock EC units to SI units (W,kW,mW) + /// + /// input EC units amount + /// OUTPUT Unit string + /// converted SI units amount + public static double ConvertECtoSI(double EC, out string Unit) + { + double outputECSI = EC; + outputECSI *= 1000; //Watts (W) + Unit = "W"; + if (outputECSI > 1000) + { + outputECSI /= 1000; //KiloWatts + Unit = "kW"; + } + if (outputECSI > 1000) + { + outputECSI /= 1000; //MegaWatts + Unit = "mW"; + } + return outputECSI; + } + + #endregion Resources + + #region GUI&Window + // GUI & Window Methods + + public static int scaledScreenHeight = 1; + public static int scaledScreenWidth = 1; + private static bool scaledScreenset; + + internal static void setScaledScreen() + { + scaledScreenHeight = Mathf.RoundToInt(Screen.height / 1); + scaledScreenWidth = Mathf.RoundToInt(Screen.width / 1); + scaledScreenset = true; + } + + internal static RectOffset SetRectOffset(RectOffset tmpRectOffset, int intValue) + { + return SetRectOffset(tmpRectOffset, intValue, intValue, intValue, intValue); + } + + internal static RectOffset SetRectOffset(RectOffset tmpRectOffset, int Left, int Right, int Top, int Bottom) + { + tmpRectOffset.left = Left; + tmpRectOffset.top = Top; + tmpRectOffset.right = Right; + tmpRectOffset.bottom = Bottom; + return tmpRectOffset; + } + + //Tooltip variables + //Store the tooltip text from throughout the code + internal static String strToolTipText = ""; + internal static String strLastTooltipText = ""; + //is it displayed and where + internal static Boolean blnToolTipDisplayed; + internal static Rect rectToolTipPosition; + internal static Int32 intTooltipVertOffset = 12; + internal static Int32 intTooltipMaxWidth = 250; + //timer so it only displays for a period of time + internal static float fltTooltipTime; + internal static float fltMaxToolTipTime = 15f; + internal static GUIStyle _TooltipStyle; + + // The following two methods are derived from Kerbal Alarm Clock mod. Which is licensed under: + //The MIT License(MIT) Copyright(c) 2014, David Tregoning + // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal + // in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + // THE SOFTWARE. + internal static void DrawToolTip() + { + if (strToolTipText != "" && (fltTooltipTime < fltMaxToolTipTime)) + { + GUIContent contTooltip = new GUIContent(strToolTipText); + if (!blnToolTipDisplayed || (strToolTipText != strLastTooltipText)) + { + //reset display time if text changed + fltTooltipTime = 0f; + //Calc the size of the Tooltip + rectToolTipPosition = new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y + intTooltipVertOffset, 0, 0); + float minwidth, maxwidth; + if (_TooltipStyle == null) + { + Log("Missing _TooltipStyle definition, cannot draw tooltips"); + return; + } + _TooltipStyle.CalcMinMaxWidth(contTooltip, out minwidth, out maxwidth); // figure out how wide one line would be + rectToolTipPosition.width = Math.Min(intTooltipMaxWidth - _TooltipStyle.padding.horizontal, maxwidth); //then work out the height with a max width + rectToolTipPosition.height = _TooltipStyle.CalcHeight(contTooltip, rectToolTipPosition.width); // heers the result + //Make sure its not off the right of the screen + if (rectToolTipPosition.x + rectToolTipPosition.width > Screen.width) rectToolTipPosition.x = Screen.width - rectToolTipPosition.width; + } + //Draw the Tooltip + GUI.Label(rectToolTipPosition, contTooltip, _TooltipStyle); + //On top of everything + GUI.depth = 0; + + //update how long the tip has been on the screen and reset the flags + fltTooltipTime += Time.deltaTime; + blnToolTipDisplayed = true; + } + else + { + //clear the flags + blnToolTipDisplayed = false; + } + if (strToolTipText != strLastTooltipText) fltTooltipTime = 0f; + strLastTooltipText = strToolTipText; + } + + internal static void SetTooltipText() + { + if (Event.current.type == EventType.Repaint) + { + strToolTipText = GUI.tooltip; + } + } + + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + public static string WordWrap(string text, int maxLineLength) + { + var sb = new StringBuilder(); + char[] prc = { ' ', ',', '.', '?', '!', ':', ';', '-' }; + char[] ws = { ' ' }; + + foreach (string line in text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) + { + int currentIndex; + int lastWrap = 0; + do + { + currentIndex = lastWrap + maxLineLength > line.Length ? line.Length : line.LastIndexOfAny(prc, Math.Min(line.Length - 1, lastWrap + maxLineLength)) + 1; + if (currentIndex <= lastWrap) + currentIndex = Math.Min(lastWrap + maxLineLength, line.Length); + sb.AppendLine(line.Substring(lastWrap, currentIndex - lastWrap).Trim(ws)); + lastWrap = currentIndex; + } while (currentIndex < line.Length); + } + return sb.ToString(); + } + + /// + /// Displays a horizontal list of toggles and returns the index of the selected item. + /// all you have to do is check items[selected] to see what is selected. + /// + public static int ToggleList(int selected, GUIContent[] items, GUIStyle[] styles, float width) + { + // Keep the selected index within the bounds of the items array + selected = selected < 0 ? 0 : selected >= items.Length ? items.Length - 1 : selected; + + GUILayout.BeginHorizontal(); + for (int i = 0; i < items.Length; i++) + { + // Display toggle. Get if toggle changed. + bool change = GUILayout.Toggle(selected == i, items[i], styles[i], GUILayout.Width(width)); + // If changed, set selected to current index. + if (change) + selected = i; + } + GUILayout.EndHorizontal(); + + // Return the currently selected item's index + return selected; + } + + //Returns True if the PauseMenu is open. Because the GameEvent callbacks don't work on the mainmenu. + internal static bool isPauseMenuOpen + { + get + { + try + { + + return PauseMenu.isOpen; + } + catch(Exception) + { + return false; + } + } + } + /// + ///Will delete Screen Messages. If you pass in messagetext it will only delete messages that contain that text string. + ///If you pass in a messagearea it will only delete messages in that area. Values are: UC,UL,UR,LC,ALL + /// + /// Specify a string that is part of a message that you want to remove, or pass in empty string to delete all messages + /// Specify a string representing the message area of the screen that you want messages removed from, + /// or pass in "ALL" string to delete from all message areas. + /// messagearea accepts the values of "UC" - UpperCenter, "UL" - UpperLeft, "UR" - UpperRight, "LC" - LowerCenter, "ALL" - All Message Areas + internal static void DeleteScreenMessages(string messagetext, string messagearea) + { + //Get the ScreenMessages Instance + var messages = ScreenMessages.Instance; + List messagetexts = new List(); + //Get the message Area messages based on the value of messagearea parameter. + switch (messagearea) + { + case "UC": + messagetexts = messages.upperCenter.gameObject.GetComponentsInChildren().ToList(); + break; + case "UL": + messagetexts = messages.upperLeft.gameObject.GetComponentsInChildren().ToList(); + break; + case "UR": + messagetexts = messages.upperRight.gameObject.GetComponentsInChildren().ToList(); + break; + case "LC": + messagetexts = messages.lowerCenter.gameObject.GetComponentsInChildren().ToList(); + break; + case "ALL": + messagetexts = messages.gameObject.GetComponentsInChildren().ToList(); + break; + } + //Loop through all the mesages we found. + List activemessagelist = ScreenMessages.Instance.ActiveMessages; + foreach (var msgtext in messagetexts) + { + //If the user specified text to search for only delete messages that contain that text. + if (messagetext != "") + { + if (msgtext != null && msgtext.text.text.Contains(messagetext)) + { + Object.Destroy(msgtext.gameObject); + } + } + else //If the user did not specific a message text to search for we DELETE ALL messages!! + { + Object.Destroy(msgtext.gameObject); + } + } + } + + #endregion GUI&Window + + #region ConfigNodes + // Get Config Node Values out of a config node Methods + + internal static Guid GetNodeValue(ConfigNode confignode, string fieldname) + { + if (confignode.HasValue(fieldname)) + { + try + { + Guid id = new Guid(confignode.GetValue(fieldname)); + return id; + } + catch (Exception ex) + { + Debug.Log("Unable to getNodeValue " + fieldname + " from " + confignode); + Debug.Log("Err: " + ex); + return Guid.Empty; + } + } + return Guid.Empty; + } + + internal static T GetNodeValue(ConfigNode confignode, string fieldname, T defaultValue) where T : IComparable, IFormattable, IConvertible + { + if (confignode.HasValue(fieldname)) + { + string stringValue = confignode.GetValue(fieldname); + if (Enum.IsDefined(typeof(T), stringValue)) + { + return (T)Enum.Parse(typeof(T), stringValue); + } + } + return defaultValue; + } + #endregion ConfigNodes + + #region Time + //Formatting time functions + + private static int y, d, h, m; + private static List parts = new List(); + //Format a Time double variable into format "xxxx:year xxxx:days xxxx:hours xxxx:mins x:xx:secs" + //Future expansion required to format to different formats. + public static String formatTime(double seconds) + { + y = (int)(seconds / (6.0 * 60.0 * 60.0 * 426.08)); + seconds = seconds % (6.0 * 60.0 * 60.0 * 426.08); + d = (int)(seconds / (6.0 * 60.0 * 60.0)); + seconds = seconds % (6.0 * 60.0 * 60.0); + h = (int)(seconds / (60.0 * 60.0)); + seconds = seconds % (60.0 * 60.0); + m = (int)(seconds / 60.0); + seconds = seconds % 60.0; + + //List parts = new List(); + parts.Clear(); + + if (y > 0) + { + parts.Add(String.Format("{0}:year ", y)); + } + + if (d > 0) + { + parts.Add(String.Format("{0}:days ", d)); + } + + if (h > 0) + { + parts.Add(String.Format("{0}:hours ", h)); + } + + if (m > 0) + { + parts.Add(String.Format("{0}:mins ", m)); + } + + if (seconds > 0) + { + parts.Add(String.Format("{0:00}:secs ", seconds)); + } + + if (parts.Count > 0) + { + return String.Join(" ", parts.ToArray()); + } + return "0s"; + } + + private static string outputstring; + private static int[] datestructure = new int[5]; + //Format a Time double variable into format "YxxxxDxxxhh:mm:ss" + //Future expansion required to format to different formats. + internal static string FormatDateString(double time) + { + outputstring = String.Empty; + //int[] datestructure = new int[5]; + if (GameSettings.KERBIN_TIME) + { + datestructure[0] = (int)time / 60 / 60 / 6 / 426; // Years + datestructure[1] = (int)time / 60 / 60 / 6 % 426; // Days + datestructure[2] = (int)time / 60 / 60 % 6; // Hours + datestructure[3] = (int)time / 60 % 60; // Minutes + datestructure[4] = (int)time % 60; //seconds + } + else + { + datestructure[0] = (int)time / 60 / 60 / 24 / 365; // Years + datestructure[1] = (int)time / 60 / 60 / 24 % 365; // Days + datestructure[2] = (int)time / 60 / 60 % 24; // Hours + datestructure[3] = (int)time / 60 % 60; // Minutes + datestructure[4] = (int)time % 60; //seconds + } + if (datestructure[0] > 0) + outputstring += "Y" + datestructure[0].ToString("####") + ":"; + if (datestructure[1] > 0) + outputstring += "D" + datestructure[1].ToString("###") + ":"; + outputstring += datestructure[2].ToString("00:"); + outputstring += datestructure[3].ToString("00:"); + outputstring += datestructure[4].ToString("00"); + return outputstring; + } + + // Electricity and temperature functions are only valid if timewarp factor is < 5. + internal static bool timewarpIsValid(int max) + { + return TimeWarp.CurrentRateIndex < max; + } + + internal static void stopWarp() + { + TimeWarp.SetRate(0, false); + } + + #endregion Time + + #region Strings + /// + /// Removes a String A from String B. + /// + internal static string RemoveSubStr(string B, string A) + { + StringBuilder b = new StringBuilder(B); + b.Replace(A, String.Empty); + return b.ToString(); + } + + public enum ISRUStatus + { + Inactive, + Active, + MissingResource, + OutputFull, + ZeroEfficiency + + } + + private static ISRUStatus returnStatus; + /// + /// Returns a Status Indicating the Status of a ISRU ModuleResourceConverter, given that it's actual status can be active, but not actually doing anything. + /// + internal static ISRUStatus GetModResConverterStatus(ModuleResourceConverter tmpRegRc) + { + returnStatus = ISRUStatus.Inactive; + if (!tmpRegRc.IsActivated) return ISRUStatus.Inactive; //If it's not Activated, it must be inactive. + // Otherwise it's Activated, but is it really working and using EC? Get it's real status. + if (tmpRegRc.status.ToLower().Contains("inactive")) returnStatus = ISRUStatus.Inactive; //Status is inactive, it's inactive.. Not sure how but sometimes this remains on load even when it's inactive? Hence the test above. + if (tmpRegRc.status.ToLower().Contains("missing")) returnStatus = ISRUStatus.MissingResource; //Missing an Input resource makes this appear in the status. + if (tmpRegRc.status.ToLower().Contains("full")) returnStatus = ISRUStatus.OutputFull; //If the vessel has nowhere to store the output, full appears in the status. + if (tmpRegRc.status.ToLower().Contains("output cap")) returnStatus = ISRUStatus.OutputFull; //If the vessel has nowhere to store the output, output cap: x% appears in the status. + if (tmpRegRc.status.ToLower().Contains("load")) returnStatus = ISRUStatus.Active; //a Percentage Load indicates it is active and actually processing... except when it gets stuck on this. + if (tmpRegRc.status.ToLower().Contains("zero efficiency")) returnStatus = ISRUStatus.ZeroEfficiency; //Efficiency has reduced to zero (heat factor?). + if (tmpRegRc.status.ToLower().Contains("operational")) returnStatus = ISRUStatus.Active; //a new status with KSP 1.1.3. + return returnStatus; + } + + #endregion Strings + + #region ModsInstalled + + private static Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + internal static bool IsRTInstalled + { + get + { + return IsModInstalled("RemoteTech"); + } + } + + internal static bool IsKopInstalled + { + get + { + return IsModInstalled("Kopernicus"); + } + } + + internal static bool IsRSSInstalled + { + get + { + return IsModInstalled("RealSolarSystem"); + } + } + + internal static bool IsResearchBodiesInstalled + { + get + { + return IsModInstalled("ResearchBodies"); + } + } + + internal static bool IsTSTInstalled + { + get + { + return IsModInstalled("TarsierSpaceTech"); + } + } + + internal static bool IsEVEInstalled + { + get + { + return IsModInstalled("EVEManager"); + + } + } + + internal static bool IsROInstalled + { + get + { + return IsModInstalled("RealismOverhaul"); + + } + } + + internal static bool IsOPMInstalled + { + get + { + CelestialBody sarnus = FlightGlobals.Bodies.FirstOrDefault(a => a.name == "Sarnus"); + if (sarnus != null) + { + return true; + } + return false; + } + } + + internal static bool IsNHInstalled + { + get + { + CelestialBody sonnah = FlightGlobals.Bodies.FirstOrDefault(a => a.name == "Sonnah"); + if (sonnah != null) + { + return true; + } + return false; + } + } + + internal static bool IsModInstalled(string assemblyName) + { + Assembly assembly = (from a in assemblies + where a.FullName.Contains(assemblyName) + select a).FirstOrDefault(); + return assembly != null; + } + + #endregion ModsInstalled + + #region Logging + // Logging Functions + // Name of the Assembly that is running this MonoBehaviour + internal static String _AssemblyName + { get { return Assembly.GetExecutingAssembly().GetName().Name; } } + + internal static bool debuggingOn = false; + + /// + /// 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 Log_Debug(String Message, params object[] strParams) + { + if (debuggingOn) + { + Log("DEBUG: " + Message, strParams); + } + } + + /// + /// Logging to the log file + /// + /// Text to be printed - can be formatted as per String.format + /// Objects to feed into a String.format + + internal static void Log(String Message, params object[] strParams) + { + Message = String.Format(Message, strParams); // This fills the params into the message + String strMessageLine = String.Format("{0},{2},{1}", + DateTime.Now, Message, + _AssemblyName); // This adds our standardised wrapper to each line + Debug.Log(strMessageLine); // And this puts it in the log + } + #endregion Logging + } +} \ No newline at end of file diff --git a/REPOSoftTechUtils/RectExtentions.cs b/REPOSoftTechUtils/RectExtentions.cs new file mode 100644 index 0000000..d4fa8ea --- /dev/null +++ b/REPOSoftTechUtils/RectExtentions.cs @@ -0,0 +1,58 @@ +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +using UnityEngine; + +namespace RSTUtils.Extensions +{ + public static class RectExtensions + { + /// + /// Clamps the rectangle inside the screen region. + /// + public static Rect ClampInsideScreen(this Rect value) + { + value.x = Mathf.Clamp(value.x, 0, Screen.width - value.width); + value.y = Mathf.Clamp(value.y, 0, Screen.height - value.height); + + return value; + } + + /// + /// Clamps the rectangle into the screen region by the specified margin. + /// + public static Rect ClampToScreen(this Rect value, float margin = 25.0f) + { + value.x = Mathf.Clamp(value.x, -(value.width - margin), Screen.width - margin); + value.y = Mathf.Clamp(value.y, -(value.height - margin), Screen.height - margin); + + return value; + } + + /// + /// Returns whether the mouse is within the coordinates of this rectangle. + /// + public static bool MouseIsOver(this Rect value) + { + return value.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y)); + } + + public static Rect Translate(this Rect value, Rect rectangle) + { + value.x += rectangle.x; + value.y += rectangle.y; + + return value; + } + } +} \ No newline at end of file diff --git a/REPOSoftTechUtils/StringFormatter/Arg.cs b/REPOSoftTechUtils/StringFormatter/Arg.cs new file mode 100644 index 0000000..d72a19d --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/Arg.cs @@ -0,0 +1,593 @@ + + +// This file is auto-generated from the Arg.tt T4 template. + +// The types here are used to forward arguments through to the string +// formatter routine without introducing any copying of the argument +// (if it's a value type) and preserving its statically known type via +// the generic type parameters. + +// The switch statement in each Format() method looks ugly but gets +// translated by the compiler into a nice direct jump table. + +using System.Runtime.CompilerServices; + +namespace System.Text.Formatting { + /// + /// A low-allocation version of the built-in type. + /// + partial class StringBuffer { + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + public void AppendFormat(string format, T0 arg0) { + var args = new Arg1(__makeref(arg0)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + public static string Format(string format, T0 arg0) { + var buffer = Acquire(format.Length + 8); + buffer.AppendFormat(format, arg0); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + public void AppendFormat(string format, T0 arg0, T1 arg1) { + var args = new Arg2(__makeref(arg0), __makeref(arg1)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + public static string Format(string format, T0 arg0, T1 arg1) { + var buffer = Acquire(format.Length + 16); + buffer.AppendFormat(format, arg0, arg1); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public void AppendFormat(string format, T0 arg0, T1 arg1, T2 arg2) { + var args = new Arg3(__makeref(arg0), __makeref(arg1), __makeref(arg2)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public static string Format(string format, T0 arg0, T1 arg1, T2 arg2) { + var buffer = Acquire(format.Length + 24); + buffer.AppendFormat(format, arg0, arg1, arg2); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public void AppendFormat(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3) { + var args = new Arg4(__makeref(arg0), __makeref(arg1), __makeref(arg2), __makeref(arg3)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public static string Format(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3) { + var buffer = Acquire(format.Length + 32); + buffer.AppendFormat(format, arg0, arg1, arg2, arg3); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public void AppendFormat(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { + var args = new Arg5(__makeref(arg0), __makeref(arg1), __makeref(arg2), __makeref(arg3), __makeref(arg4)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public static string Format(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { + var buffer = Acquire(format.Length + 40); + buffer.AppendFormat(format, arg0, arg1, arg2, arg3, arg4); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public void AppendFormat(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { + var args = new Arg6(__makeref(arg0), __makeref(arg1), __makeref(arg2), __makeref(arg3), __makeref(arg4), __makeref(arg5)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public static string Format(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { + var buffer = Acquire(format.Length + 48); + buffer.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public void AppendFormat(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) { + var args = new Arg7(__makeref(arg0), __makeref(arg1), __makeref(arg2), __makeref(arg3), __makeref(arg4), __makeref(arg5), __makeref(arg6)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public static string Format(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) { + var buffer = Acquire(format.Length + 56); + buffer.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public void AppendFormat(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) { + var args = new Arg8(__makeref(arg0), __makeref(arg1), __makeref(arg2), __makeref(arg3), __makeref(arg4), __makeref(arg5), __makeref(arg6), __makeref(arg7)); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + + /// A value to format. + public static string Format(string format, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) { + var buffer = Acquire(format.Length + 64); + buffer.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + var result = buffer.ToString(); + Release(buffer); + return result; + } + + } + + + unsafe struct Arg1 : IArgSet { + IntPtr t0; + + + public int Count => 1; + + public Arg1 (TypedReference t0) { + this.t0 = *(IntPtr*)&t0; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + + } + } + } + + + unsafe struct Arg2 : IArgSet { + IntPtr t0; + IntPtr t1; + + + public int Count => 2; + + public Arg2 (TypedReference t0, TypedReference t1) { + this.t0 = *(IntPtr*)&t0; + this.t1 = *(IntPtr*)&t1; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + case 1: buffer.AppendGeneric(t1, format); break; + + } + } + } + + + unsafe struct Arg3 : IArgSet { + IntPtr t0; + IntPtr t1; + IntPtr t2; + + + public int Count => 3; + + public Arg3 (TypedReference t0, TypedReference t1, TypedReference t2) { + this.t0 = *(IntPtr*)&t0; + this.t1 = *(IntPtr*)&t1; + this.t2 = *(IntPtr*)&t2; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + case 1: buffer.AppendGeneric(t1, format); break; + case 2: buffer.AppendGeneric(t2, format); break; + + } + } + } + + + unsafe struct Arg4 : IArgSet { + IntPtr t0; + IntPtr t1; + IntPtr t2; + IntPtr t3; + + + public int Count => 4; + + public Arg4 (TypedReference t0, TypedReference t1, TypedReference t2, TypedReference t3) { + this.t0 = *(IntPtr*)&t0; + this.t1 = *(IntPtr*)&t1; + this.t2 = *(IntPtr*)&t2; + this.t3 = *(IntPtr*)&t3; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + case 1: buffer.AppendGeneric(t1, format); break; + case 2: buffer.AppendGeneric(t2, format); break; + case 3: buffer.AppendGeneric(t3, format); break; + + } + } + } + + + unsafe struct Arg5 : IArgSet { + IntPtr t0; + IntPtr t1; + IntPtr t2; + IntPtr t3; + IntPtr t4; + + + public int Count => 5; + + public Arg5 (TypedReference t0, TypedReference t1, TypedReference t2, TypedReference t3, TypedReference t4) { + this.t0 = *(IntPtr*)&t0; + this.t1 = *(IntPtr*)&t1; + this.t2 = *(IntPtr*)&t2; + this.t3 = *(IntPtr*)&t3; + this.t4 = *(IntPtr*)&t4; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + case 1: buffer.AppendGeneric(t1, format); break; + case 2: buffer.AppendGeneric(t2, format); break; + case 3: buffer.AppendGeneric(t3, format); break; + case 4: buffer.AppendGeneric(t4, format); break; + + } + } + } + + + unsafe struct Arg6 : IArgSet { + IntPtr t0; + IntPtr t1; + IntPtr t2; + IntPtr t3; + IntPtr t4; + IntPtr t5; + + + public int Count => 6; + + public Arg6 (TypedReference t0, TypedReference t1, TypedReference t2, TypedReference t3, TypedReference t4, TypedReference t5) { + this.t0 = *(IntPtr*)&t0; + this.t1 = *(IntPtr*)&t1; + this.t2 = *(IntPtr*)&t2; + this.t3 = *(IntPtr*)&t3; + this.t4 = *(IntPtr*)&t4; + this.t5 = *(IntPtr*)&t5; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + case 1: buffer.AppendGeneric(t1, format); break; + case 2: buffer.AppendGeneric(t2, format); break; + case 3: buffer.AppendGeneric(t3, format); break; + case 4: buffer.AppendGeneric(t4, format); break; + case 5: buffer.AppendGeneric(t5, format); break; + + } + } + } + + + unsafe struct Arg7 : IArgSet { + IntPtr t0; + IntPtr t1; + IntPtr t2; + IntPtr t3; + IntPtr t4; + IntPtr t5; + IntPtr t6; + + + public int Count => 7; + + public Arg7 (TypedReference t0, TypedReference t1, TypedReference t2, TypedReference t3, TypedReference t4, TypedReference t5, TypedReference t6) { + this.t0 = *(IntPtr*)&t0; + this.t1 = *(IntPtr*)&t1; + this.t2 = *(IntPtr*)&t2; + this.t3 = *(IntPtr*)&t3; + this.t4 = *(IntPtr*)&t4; + this.t5 = *(IntPtr*)&t5; + this.t6 = *(IntPtr*)&t6; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + case 1: buffer.AppendGeneric(t1, format); break; + case 2: buffer.AppendGeneric(t2, format); break; + case 3: buffer.AppendGeneric(t3, format); break; + case 4: buffer.AppendGeneric(t4, format); break; + case 5: buffer.AppendGeneric(t5, format); break; + case 6: buffer.AppendGeneric(t6, format); break; + + } + } + } + + + unsafe struct Arg8 : IArgSet { + IntPtr t0; + IntPtr t1; + IntPtr t2; + IntPtr t3; + IntPtr t4; + IntPtr t5; + IntPtr t6; + IntPtr t7; + + + public int Count => 8; + + public Arg8 (TypedReference t0, TypedReference t1, TypedReference t2, TypedReference t3, TypedReference t4, TypedReference t5, TypedReference t6, TypedReference t7) { + this.t0 = *(IntPtr*)&t0; + this.t1 = *(IntPtr*)&t1; + this.t2 = *(IntPtr*)&t2; + this.t3 = *(IntPtr*)&t3; + this.t4 = *(IntPtr*)&t4; + this.t5 = *(IntPtr*)&t5; + this.t6 = *(IntPtr*)&t6; + this.t7 = *(IntPtr*)&t7; + + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { + case 0: buffer.AppendGeneric(t0, format); break; + case 1: buffer.AppendGeneric(t1, format); break; + case 2: buffer.AppendGeneric(t2, format); break; + case 3: buffer.AppendGeneric(t3, format); break; + case 4: buffer.AppendGeneric(t4, format); break; + case 5: buffer.AppendGeneric(t5, format); break; + case 6: buffer.AppendGeneric(t6, format); break; + case 7: buffer.AppendGeneric(t7, format); break; + + } + } + } +} \ No newline at end of file diff --git a/REPOSoftTechUtils/StringFormatter/Arg.tt b/REPOSoftTechUtils/StringFormatter/Arg.tt new file mode 100644 index 0000000..c51c17c --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/Arg.tt @@ -0,0 +1,85 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +// This file is auto-generated from the Arg.tt T4 template. + +// The types here are used to forward arguments through to the string +// formatter routine without introducing any copying of the argument +// (if it's a value type) and preserving its statically known type via +// the generic type parameters. + +// The switch statement in each Format() method looks ugly but gets +// translated by the compiler into a nice direct jump table. + +using System.Runtime.CompilerServices; + +namespace System.Text.Formatting { + /// + /// A low-allocation version of the built-in type. + /// + partial class StringBuffer {<# for(int i = 1; i <= 8; i++) { + var simpleName = "Arg" + i; + var genericParams = " + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. Each format item is replaced by the string representation of a single argument. + /// + /// A composite format string.<#for(int j = 0; j < i; j++) { +#> + + /// A value to format.<#}#> + public void AppendFormat<#=genericParams#>(string format, T0 arg0<#for(int j = 1; j < i; j++) { #>, T<#=j#> arg<#=j#><#}#>) { + var args = new <#=fullName#>(__makeref(arg0)<#for(int j = 1; j < i; j++) { #>, __makeref(arg<#=j#>)<#}#>); + AppendArgSet(format, ref args); + } + + /// + /// Converts the value of objects to strings based on the formats specified and inserts them into another string. + /// + /// A composite format string.<#for(int j = 0; j < i; j++) { +#> + + /// A value to format.<#}#> + public static string Format<#=genericParams#>(string format, T0 arg0<#for(int j = 1; j < i; j++) { #>, T<#=j#> arg<#=j#><#}#>) { + var buffer = Acquire(format.Length + <#=i * 8#>); + buffer.AppendFormat(format, arg0<#for(int j = 1; j < i; j++) { #>, arg<#=j#><#}#>); + var result = buffer.ToString(); + Release(buffer); + return result; + } +<#}#> + } +<# for(int i = 1; i <= 8; i++) { + var simpleName = "Arg" + i; + var fullName = simpleName + " + + unsafe struct <#=fullName#> : IArgSet { +<#for(int j = 0; j < i; j++) { #> IntPtr t<#=j#>; +<#}#> + + public int Count => <#=i#>; + + public <#=simpleName#> (TypedReference t0<#for(int j = 1; j < i; j++) { #>, TypedReference t<#=j#><#}#>) { + <#for(int j = 0; j < i; j++) { #> this.t<#=j#> = *(IntPtr*)&t<#=j#>; + <#}#> + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Format (StringBuffer buffer, int index, StringView format) { + switch (index) { +<#for(int j = 0; j < i; j++) { #> case <#=j#>: buffer.AppendGeneric>(t<#=j#>, format); break; +<#}#> + } + } + } +<#}#>} \ No newline at end of file diff --git a/REPOSoftTechUtils/StringFormatter/Culture.cs b/REPOSoftTechUtils/StringFormatter/Culture.cs new file mode 100644 index 0000000..f03c04c --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/Culture.cs @@ -0,0 +1,176 @@ +using System.Globalization; + +namespace System.Text.Formatting { + // caches formatting information from culture data + // some of the accessors on NumberFormatInfo allocate copies of their data + sealed class CachedCulture { + public readonly CultureInfo Culture; + + public readonly NumberFormatData CurrencyData; + public readonly NumberFormatData FixedData; + public readonly NumberFormatData NumberData; + public readonly NumberFormatData ScientificData; + public readonly NumberFormatData PercentData; + + public readonly string CurrencyNegativePattern; + public readonly string CurrencyPositivePattern; + public readonly string CurrencySymbol; + + public readonly string NumberNegativePattern; + public readonly string NumberPositivePattern; + + public readonly string PercentNegativePattern; + public readonly string PercentPositivePattern; + public readonly string PercentSymbol; + + public readonly string NegativeSign; + public readonly string PositiveSign; + + public readonly string NaN; + public readonly string PositiveInfinity; + public readonly string NegativeInfinity; + + public readonly int DecimalBufferSize; + + public CachedCulture (CultureInfo culture) { + Culture = culture; + + var info = culture.NumberFormat; + CurrencyData = new NumberFormatData( + info.CurrencyDecimalDigits, + info.NegativeSign, + info.CurrencyDecimalSeparator, + info.CurrencyGroupSeparator, + info.CurrencyGroupSizes, + info.CurrencySymbol.Length + ); + + FixedData = new NumberFormatData( + info.NumberDecimalDigits, + info.NegativeSign, + info.NumberDecimalSeparator, + null, + null, + 0 + ); + + NumberData = new NumberFormatData( + info.NumberDecimalDigits, + info.NegativeSign, + info.NumberDecimalSeparator, + info.NumberGroupSeparator, + info.NumberGroupSizes, + 0 + ); + + ScientificData = new NumberFormatData( + 6, + info.NegativeSign, + info.NumberDecimalSeparator, + null, + null, + info.NegativeSign.Length + info.PositiveSign.Length * 2 // for number and exponent + ); + + PercentData = new NumberFormatData( + info.PercentDecimalDigits, + info.NegativeSign, + info.PercentDecimalSeparator, + info.PercentGroupSeparator, + info.PercentGroupSizes, + info.PercentSymbol.Length + ); + + CurrencyNegativePattern = NegativeCurrencyFormats[info.CurrencyNegativePattern]; + CurrencyPositivePattern = PositiveCurrencyFormats[info.CurrencyPositivePattern]; + CurrencySymbol = info.CurrencySymbol; + NumberNegativePattern = NegativeNumberFormats[info.NumberNegativePattern]; + NumberPositivePattern = PositiveNumberFormat; + PercentNegativePattern = NegativePercentFormats[info.PercentNegativePattern]; + PercentPositivePattern = PositivePercentFormats[info.PercentPositivePattern]; + PercentSymbol = info.PercentSymbol; + NegativeSign = info.NegativeSign; + PositiveSign = info.PositiveSign; + NaN = info.NaNSymbol; + PositiveInfinity = info.PositiveInfinitySymbol; + NegativeInfinity = info.NegativeInfinitySymbol; + DecimalBufferSize = + NumberFormatData.MinBufferSize + + info.NumberDecimalSeparator.Length + + (NegativeSign.Length + PositiveSign.Length) * 2; + } + + static readonly string[] PositiveCurrencyFormats = { + "$#", "#$", "$ #", "# $" + }; + + static readonly string[] NegativeCurrencyFormats = { + "($#)", "-$#", "$-#", "$#-", + "(#$)", "-#$", "#-$", "#$-", + "-# $", "-$ #", "# $-", "$ #-", + "$ -#", "#- $", "($ #)", "(# $)" + }; + + static readonly string[] PositivePercentFormats = { + "# %", "#%", "%#", "% #" + }; + + static readonly string[] NegativePercentFormats = { + "-# %", "-#%", "-%#", + "%-#", "%#-", + "#-%", "#%-", + "-% #", "# %-", "% #-", + "% -#", "#- %" + }; + + static readonly string[] NegativeNumberFormats = { + "(#)", "-#", "- #", "#-", "# -", + }; + + static readonly string PositiveNumberFormat = "#"; + } + + // contains format information for a specific kind of format string + // e.g. (fixed, number, currency) + sealed class NumberFormatData { + readonly int bufferLength; + readonly int perDigitLength; + + public readonly int DecimalDigits; + public readonly string NegativeSign; + public readonly string DecimalSeparator; + public readonly string GroupSeparator; + public readonly int[] GroupSizes; + + public NumberFormatData (int decimalDigits, string negativeSign, string decimalSeparator, string groupSeparator, int[] groupSizes, int extra) { + DecimalDigits = decimalDigits; + NegativeSign = negativeSign; + DecimalSeparator = decimalSeparator; + GroupSeparator = groupSeparator; + GroupSizes = groupSizes; + + bufferLength = MinBufferSize; + bufferLength += NegativeSign.Length; + bufferLength += DecimalSeparator.Length; + bufferLength += extra; + + if (GroupSeparator != null) + perDigitLength = GroupSeparator.Length; + } + + public int GetBufferSize (ref int maxDigits, int scale) { + if (maxDigits < 0) + maxDigits = DecimalDigits; + + var digitCount = scale >= 0 ? scale + maxDigits : 0; + long len = bufferLength; + + // calculate buffer size + len += digitCount; + len += perDigitLength * digitCount; + return checked((int)len); + } + + internal const int MinBufferSize = 105; + } +} diff --git a/REPOSoftTechUtils/StringFormatter/CustomNumeric.cs b/REPOSoftTechUtils/StringFormatter/CustomNumeric.cs new file mode 100644 index 0000000..c2e7d23 --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/CustomNumeric.cs @@ -0,0 +1,8 @@ + +namespace System.Text.Formatting { + // this file contains the custom numeric formatting routines split out from the Numeric.cs file + partial class Numeric { + static void NumberToCustomFormatString (StringBuffer formatter, ref Number number, StringView specifier, CachedCulture culture) { + } + } +} diff --git a/REPOSoftTechUtils/StringFormatter/Numeric.cs b/REPOSoftTechUtils/StringFormatter/Numeric.cs new file mode 100644 index 0000000..62d254c --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/Numeric.cs @@ -0,0 +1,1084 @@ +using System.Runtime.CompilerServices; + + +namespace System.Text.Formatting { + // Most of the implementation of this file was ported from the native versions built into the CLR + // See: https://github.com/dotnet/coreclr/blob/838807429a0828a839958e3b7d392d65886c8f2e/src/classlibnative/bcltype/number.cpp + // Also see: https://github.com/dotnet/coreclr/blob/02084af832c2900cf6eac2a168c41f261409be97/src/mscorlib/src/System/Number.cs + // Standard numeric format string reference: https://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx + + unsafe static partial class Numeric { + public static void FormatSByte (StringBuffer formatter, sbyte value, StringView specifier, CachedCulture culture) { + if (value < 0 && !specifier.IsEmpty) { + // if we're negative and doing a hex format, mask out the bits for the conversion + char c = specifier.Data[0]; + if (c == 'X' || c == 'x') + FormatUInt32(formatter, (uint)(value & 0xFF), specifier, culture); + } + + FormatInt32(formatter, value, specifier, culture); + } + + public static void FormatInt16 (StringBuffer formatter, short value, StringView specifier, CachedCulture culture) { + if (value < 0 && !specifier.IsEmpty) { + // if we're negative and doing a hex format, mask out the bits for the conversion + char c = specifier.Data[0]; + if (c == 'X' || c == 'x') + FormatUInt32(formatter, (uint)(value & 0xFFFF), specifier, culture); + } + + FormatInt32(formatter, value, specifier, culture); + } + + public static void FormatInt32 (StringBuffer formatter, int value, StringView specifier, CachedCulture culture) { + int digits; + var fmt = ParseFormatSpecifier(specifier, out digits); + + // ANDing with 0xFFDF has the effect of uppercasing the character + switch (fmt & 0xFFDF) { + case 'G': + if (digits > 0) + goto default; + else + goto case 'D'; + + case 'D': + Int32ToDecStr(formatter, value, digits, culture.NegativeSign); + break; + + case 'X': + // fmt-('X'-'A'+1) gives us the base hex character in either + // uppercase or lowercase, depending on the casing of fmt + Int32ToHexStr(formatter, (uint)value, fmt - ('X' - 'A' + 10), digits); + break; + + default: + var number = new Number(); + var buffer = stackalloc char[MaxNumberDigits + 1]; + number.Digits = buffer; + Int32ToNumber(value, ref number); + if (fmt != 0) + NumberToString(formatter, ref number, fmt, digits, culture); + else + NumberToCustomFormatString(formatter, ref number, specifier, culture); + break; + } + } + + public static void FormatUInt32 (StringBuffer formatter, uint value, StringView specifier, CachedCulture culture) { + int digits; + var fmt = ParseFormatSpecifier(specifier, out digits); + + // ANDing with 0xFFDF has the effect of uppercasing the character + switch (fmt & 0xFFDF) { + case 'G': + if (digits > 0) + goto default; + else + goto case 'D'; + + case 'D': + UInt32ToDecStr(formatter, value, digits); + break; + + case 'X': + // fmt-('X'-'A'+1) gives us the base hex character in either + // uppercase or lowercase, depending on the casing of fmt + Int32ToHexStr(formatter, value, fmt - ('X' - 'A' + 10), digits); + break; + + default: + var number = new Number(); + var buffer = stackalloc char[MaxNumberDigits + 1]; + number.Digits = buffer; + UInt32ToNumber(value, ref number); + if (fmt != 0) + NumberToString(formatter, ref number, fmt, digits, culture); + else + NumberToCustomFormatString(formatter, ref number, specifier, culture); + break; + } + } + + public static void FormatInt64 (StringBuffer formatter, long value, StringView specifier, CachedCulture culture) { + int digits; + var fmt = ParseFormatSpecifier(specifier, out digits); + + // ANDing with 0xFFDF has the effect of uppercasing the character + switch (fmt & 0xFFDF) { + case 'G': + if (digits > 0) + goto default; + else + goto case 'D'; + + case 'D': + Int64ToDecStr(formatter, value, digits, culture.NegativeSign); + break; + + case 'X': + // fmt-('X'-'A'+1) gives us the base hex character in either + // uppercase or lowercase, depending on the casing of fmt + Int64ToHexStr(formatter, (ulong)value, fmt - ('X' - 'A' + 10), digits); + break; + + default: + var number = new Number(); + var buffer = stackalloc char[MaxNumberDigits + 1]; + number.Digits = buffer; + Int64ToNumber(value, ref number); + if (fmt != 0) + NumberToString(formatter, ref number, fmt, digits, culture); + else + NumberToCustomFormatString(formatter, ref number, specifier, culture); + break; + } + } + + public static void FormatUInt64 (StringBuffer formatter, ulong value, StringView specifier, CachedCulture culture) { + int digits; + var fmt = ParseFormatSpecifier(specifier, out digits); + + // ANDing with 0xFFDF has the effect of uppercasing the character + switch (fmt & 0xFFDF) { + case 'G': + if (digits > 0) + goto default; + else + goto case 'D'; + + case 'D': + UInt64ToDecStr(formatter, value, digits); + break; + + case 'X': + // fmt-('X'-'A'+1) gives us the base hex character in either + // uppercase or lowercase, depending on the casing of fmt + Int64ToHexStr(formatter, value, fmt - ('X' - 'A' + 10), digits); + break; + + default: + var number = new Number(); + var buffer = stackalloc char[MaxNumberDigits + 1]; + number.Digits = buffer; + UInt64ToNumber(value, ref number); + if (fmt != 0) + NumberToString(formatter, ref number, fmt, digits, culture); + else + NumberToCustomFormatString(formatter, ref number, specifier, culture); + break; + } + } + + public static void FormatSingle (StringBuffer formatter, float value, StringView specifier, CachedCulture culture) { + int digits; + int precision = FloatPrecision; + var fmt = ParseFormatSpecifier(specifier, out digits); + + // ANDing with 0xFFDF has the effect of uppercasing the character + switch (fmt & 0xFFDF) { + case 'G': + if (digits > 7) + precision = 9; + break; + + case 'E': + if (digits > 6) + precision = 9; + break; + } + + var number = new Number(); + var buffer = stackalloc char[MaxFloatingDigits + 1]; + number.Digits = buffer; + DoubleToNumber(value, precision, ref number); + + if (number.Scale == ScaleNaN) { + formatter.Append(culture.NaN); + return; + } + + if (number.Scale == ScaleInf) { + if (number.Sign > 0) + formatter.Append(culture.NegativeInfinity); + else + formatter.Append(culture.PositiveInfinity); + return; + } + + if (fmt != 0) + NumberToString(formatter, ref number, fmt, digits, culture); + else + NumberToCustomFormatString(formatter, ref number, specifier, culture); + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void FormatDouble (StringBuffer formatter, double value, StringView specifier, CachedCulture culture) { + int digits; + int precision = DoublePrecision; + var fmt = ParseFormatSpecifier(specifier, out digits); + + // ANDing with 0xFFDF has the effect of uppercasing the character + switch (fmt & 0xFFDF) { + case 'G': + if (digits > 15) + precision = 17; + break; + + case 'E': + if (digits > 14) + precision = 17; + break; + } + + var number = new Number(); + var buffer = stackalloc char[MaxFloatingDigits + 1]; + number.Digits = buffer; + DoubleToNumber(value, precision, ref number); + + if (number.Scale == ScaleNaN) { + formatter.Append(culture.NaN); + return; + } + + if (number.Scale == ScaleInf) { + if (number.Sign > 0) + formatter.Append(culture.NegativeInfinity); + else + formatter.Append(culture.PositiveInfinity); + return; + } + + if (fmt != 0) + NumberToString(formatter, ref number, fmt, digits, culture); + else + NumberToCustomFormatString(formatter, ref number, specifier, culture); + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void FormatDecimal (StringBuffer formatter, uint* value, StringView specifier, CachedCulture culture) { + int digits; + var fmt = ParseFormatSpecifier(specifier, out digits); + + var number = new Number(); + var buffer = stackalloc char[MaxNumberDigits + 1]; + number.Digits = buffer; + DecimalToNumber(value, ref number); + if (fmt != 0) + NumberToString(formatter, ref number, fmt, digits, culture, isDecimal: true); + else + NumberToCustomFormatString(formatter, ref number, specifier, culture); + } + + static void NumberToString (StringBuffer formatter, ref Number number, char format, int maxDigits, CachedCulture culture, bool isDecimal = false) { + // ANDing with 0xFFDF has the effect of uppercasing the character + switch (format & 0xFFDF) { + case 'C': + { + var cultureData = culture.CurrencyData; + var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale); + RoundNumber(ref number, number.Scale + maxDigits); + + var buffer = stackalloc char[bufferSize]; + var ptr = FormatCurrency( + buffer, + ref number, + maxDigits, + cultureData, + number.Sign > 0 ? culture.CurrencyNegativePattern : culture.CurrencyPositivePattern, + culture.CurrencySymbol + ); + + formatter.Append(buffer, (int)(ptr - buffer)); + break; + } + + case 'F': + { + var cultureData = culture.FixedData; + var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale); + RoundNumber(ref number, number.Scale + maxDigits); + + var buffer = stackalloc char[bufferSize]; + var ptr = buffer; + if (number.Sign > 0) + AppendString(&ptr, cultureData.NegativeSign); + + ptr = FormatFixed(ptr, ref number, maxDigits, cultureData); + formatter.Append(buffer, (int)(ptr - buffer)); + break; + } + + case 'N': + { + var cultureData = culture.NumberData; + var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale); + RoundNumber(ref number, number.Scale + maxDigits); + + var buffer = stackalloc char[bufferSize]; + var ptr = FormatNumber( + buffer, + ref number, + maxDigits, + number.Sign > 0 ? culture.NumberNegativePattern : culture.NumberPositivePattern, + cultureData + ); + + formatter.Append(buffer, (int)(ptr - buffer)); + break; + } + + case 'E': + { + var cultureData = culture.ScientificData; + var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale); + maxDigits++; + + RoundNumber(ref number, maxDigits); + + var buffer = stackalloc char[bufferSize]; + var ptr = buffer; + if (number.Sign > 0) + AppendString(&ptr, cultureData.NegativeSign); + + ptr = FormatScientific( + ptr, + ref number, + maxDigits, + format, // TODO: fix casing + cultureData.DecimalSeparator, + culture.PositiveSign, + culture.NegativeSign + ); + + formatter.Append(buffer, (int)(ptr - buffer)); + break; + } + + case 'P': + { + number.Scale += 2; + var cultureData = culture.PercentData; + var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale); + RoundNumber(ref number, number.Scale + maxDigits); + + var buffer = stackalloc char[bufferSize]; + var ptr = FormatPercent( + buffer, + ref number, + maxDigits, + cultureData, + number.Sign > 0 ? culture.PercentNegativePattern : culture.PercentPositivePattern, + culture.PercentSymbol + ); + + formatter.Append(buffer, (int)(ptr - buffer)); + break; + } + + case 'G': + { + var enableRounding = true; + if (maxDigits < 1) { + if (isDecimal && maxDigits == -1) { + // if we're formatting a decimal, default to 29 digits precision + // only for G formatting without a precision specifier + maxDigits = DecimalPrecision; + enableRounding = false; + } + else + maxDigits = number.Precision; + } + + var bufferSize = maxDigits + culture.DecimalBufferSize; + var buffer = stackalloc char[bufferSize]; + var ptr = buffer; + + // round for G formatting only if a precision is given + // we need to handle the minus zero case also + if (enableRounding) + RoundNumber(ref number, maxDigits); + else if (isDecimal && number.Digits[0] == 0) + number.Sign = 0; + + if (number.Sign > 0) + AppendString(&ptr, culture.NegativeSign); + + ptr = FormatGeneral( + ptr, + ref number, + maxDigits, + (char)(format - ('G' - 'E')), + culture.NumberData.DecimalSeparator, + culture.PositiveSign, + culture.NegativeSign, + !enableRounding + ); + + formatter.Append(buffer, (int)(ptr - buffer)); + break; + } + + default: + throw new FormatException(string.Format(SR.UnknownFormatSpecifier, format)); + } + } + + static char* FormatCurrency (char* buffer, ref Number number, int maxDigits, NumberFormatData data, string currencyFormat, string currencySymbol) { + for (int i = 0; i < currencyFormat.Length; i++) { + char c = currencyFormat[i]; + switch (c) { + case '#': buffer = FormatFixed(buffer, ref number, maxDigits, data); break; + case '-': AppendString(&buffer, data.NegativeSign); break; + case '$': AppendString(&buffer, currencySymbol); break; + default: *buffer++ = c; break; + } + } + + return buffer; + } + + static char* FormatNumber (char* buffer, ref Number number, int maxDigits, string format, NumberFormatData data) { + for (int i = 0; i < format.Length; i++) { + char c = format[i]; + switch (c) { + case '#': buffer = FormatFixed(buffer, ref number, maxDigits, data); break; + case '-': AppendString(&buffer, data.NegativeSign); break; + default: *buffer++ = c; break; + } + } + + return buffer; + } + + static char* FormatPercent (char* buffer, ref Number number, int maxDigits, NumberFormatData data, string format, string percentSymbol) { + for (int i = 0; i < format.Length; i++) { + char c = format[i]; + switch (c) { + case '#': buffer = FormatFixed(buffer, ref number, maxDigits, data); break; + case '-': AppendString(&buffer, data.NegativeSign); break; + case '%': AppendString(&buffer, percentSymbol); break; + default: *buffer++ = c; break; + } + } + + return buffer; + } + + static char* FormatGeneral ( + char* buffer, ref Number number, int maxDigits, char expChar, + string decimalSeparator, string positiveSign, string negativeSign, + bool suppressScientific) { + + var digitPos = number.Scale; + var scientific = false; + if (!suppressScientific) { + if (digitPos > maxDigits || digitPos < -3) { + digitPos = 1; + scientific = true; + } + } + + var digits = number.Digits; + if (digitPos <= 0) + *buffer++ = '0'; + else { + do { + *buffer++ = *digits != 0 ? *digits++ : '0'; + } while (--digitPos > 0); + } + + if (*digits != 0 || digitPos < 0) { + AppendString(&buffer, decimalSeparator); + while (digitPos < 0) { + *buffer++ = '0'; + digitPos++; + } + + while (*digits != 0) + *buffer++ = *digits++; + } + + if (scientific) + buffer = FormatExponent(buffer, number.Scale - 1, expChar, positiveSign, negativeSign, 2); + + return buffer; + } + + static char* FormatScientific ( + char* buffer, ref Number number, int maxDigits, char expChar, + string decimalSeparator, string positiveSign, string negativeSign) { + + var digits = number.Digits; + *buffer++ = *digits != 0 ? *digits++ : '0'; + if (maxDigits != 1) + AppendString(&buffer, decimalSeparator); + + while (--maxDigits > 0) + *buffer++ = *digits != 0 ? *digits++ : '0'; + + int e = number.Digits[0] == 0 ? 0 : number.Scale - 1; + return FormatExponent(buffer, e, expChar, positiveSign, negativeSign, 3); + } + + static char* FormatExponent (char* buffer, int value, char expChar, string positiveSign, string negativeSign, int minDigits) { + *buffer++ = expChar; + if (value < 0) { + AppendString(&buffer, negativeSign); + value = -value; + } + else if (positiveSign != null) + AppendString(&buffer, positiveSign); + + var digits = stackalloc char[11]; + var ptr = Int32ToDecChars(digits + 10, (uint)value, minDigits); + var len = (int)(digits + 10 - ptr); + while (--len >= 0) + *buffer++ = *ptr++; + + return buffer; + } + + static char* FormatFixed (char* buffer, ref Number number, int maxDigits, NumberFormatData data) { + var groups = data.GroupSizes; + var digits = number.Digits; + var digitPos = number.Scale; + if (digitPos <= 0) + *buffer++ = '0'; + else if (groups != null) { + var groupIndex = 0; + var groupSizeCount = groups[0]; + var groupSizeLen = groups.Length; + var newBufferSize = digitPos; + var groupSeparatorLen = data.GroupSeparator.Length; + var groupSize = 0; + + // figure out the size of the result + if (groupSizeLen != 0) { + while (digitPos > groupSizeCount) { + groupSize = groups[groupIndex]; + if (groupSize == 0) + break; + + newBufferSize += groupSeparatorLen; + if (groupIndex < groupSizeLen - 1) + groupIndex++; + + groupSizeCount += groups[groupIndex]; + if (groupSizeCount < 0 || newBufferSize < 0) + throw new ArgumentOutOfRangeException(SR.InvalidGroupSizes); + } + + if (groupSizeCount == 0) + groupSize = 0; + else + groupSize = groups[0]; + } + + groupIndex = 0; + var digitCount = 0; + var digitLength = StrLen(digits); + var digitStart = digitPos < digitLength ? digitPos : digitLength; + var ptr = buffer + newBufferSize - 1; + + for (int i = digitPos - 1; i >= 0; i--) { + *(ptr--) = i < digitStart ? digits[i] : '0'; + + // check if we need to add a group separator + if (groupSize > 0) { + digitCount++; + if (digitCount == groupSize && i != 0) { + for (int j = groupSeparatorLen - 1; j >= 0; j--) + *(ptr--) = data.GroupSeparator[j]; + + if (groupIndex < groupSizeLen - 1) { + groupIndex++; + groupSize = groups[groupIndex]; + } + digitCount = 0; + } + } + } + + buffer += newBufferSize; + digits += digitStart; + } + else { + do { + *buffer++ = *digits != 0 ? *digits++ : '0'; + } + while (--digitPos > 0); + } + + if (maxDigits > 0) { + AppendString(&buffer, data.DecimalSeparator); + while (digitPos < 0 && maxDigits > 0) { + *buffer++ = '0'; + digitPos++; + maxDigits--; + } + + while (maxDigits > 0) { + *buffer++ = *digits != 0 ? *digits++ : '0'; + maxDigits--; + } + } + + return buffer; + } + + static void Int32ToDecStr (StringBuffer formatter, int value, int digits, string negativeSign) { + if (digits < 1) + digits = 1; + + var maxDigits = digits > 15 ? digits : 15; + var bufferLength = maxDigits > 100 ? maxDigits : 100; + var negativeLength = 0; + + if (value < 0) { + negativeLength = negativeSign.Length; + if (negativeLength > bufferLength - maxDigits) + bufferLength = negativeLength + maxDigits; + } + + var buffer = stackalloc char[bufferLength]; + var p = Int32ToDecChars(buffer + bufferLength, value >= 0 ? (uint)value : (uint)-value, digits); + if (value < 0) { + // add the negative sign + for (int i = negativeLength - 1; i >= 0; i--) + *(--p) = negativeSign[i]; + } + + formatter.Append(p, (int)(buffer + bufferLength - p)); + } + + static void UInt32ToDecStr (StringBuffer formatter, uint value, int digits) { + var buffer = stackalloc char[100]; + if (digits < 1) + digits = 1; + + var p = Int32ToDecChars(buffer + 100, value, digits); + formatter.Append(p, (int)(buffer + 100 - p)); + } + + static void Int32ToHexStr (StringBuffer formatter, uint value, int hexBase, int digits) { + var buffer = stackalloc char[100]; + if (digits < 1) + digits = 1; + + var p = Int32ToHexChars(buffer + 100, value, hexBase, digits); + formatter.Append(p, (int)(buffer + 100 - p)); + } + + static void Int64ToDecStr (StringBuffer formatter, long value, int digits, string negativeSign) { + if (digits < 1) + digits = 1; + + var sign = (int)High32((ulong)value); + var maxDigits = digits > 20 ? digits : 20; + var bufferLength = maxDigits > 100 ? maxDigits : 100; + + if (sign < 0) { + value = -value; + var negativeLength = negativeSign.Length; + if (negativeLength > bufferLength - maxDigits) + bufferLength = negativeLength + maxDigits; + } + + var buffer = stackalloc char[bufferLength]; + var p = buffer + bufferLength; + var uv = (ulong)value; + while (High32(uv) != 0) { + p = Int32ToDecChars(p, Int64DivMod(ref uv), 9); + digits -= 9; + } + + p = Int32ToDecChars(p, Low32(uv), digits); + if (sign < 0) { + // add the negative sign + for (int i = negativeSign.Length - 1; i >= 0; i--) + *(--p) = negativeSign[i]; + } + + formatter.Append(p, (int)(buffer + bufferLength - p)); + } + + static void UInt64ToDecStr (StringBuffer formatter, ulong value, int digits) { + if (digits < 1) + digits = 1; + + var buffer = stackalloc char[100]; + var p = buffer + 100; + while (High32(value) != 0) { + p = Int32ToDecChars(p, Int64DivMod(ref value), 9); + digits -= 9; + } + + p = Int32ToDecChars(p, Low32(value), digits); + formatter.Append(p, (int)(buffer + 100 - p)); + } + + static void Int64ToHexStr (StringBuffer formatter, ulong value, int hexBase, int digits) { + var buffer = stackalloc char[100]; + char* ptr; + if (High32(value) != 0) { + Int32ToHexChars(buffer + 100, Low32(value), hexBase, 8); + ptr = Int32ToHexChars(buffer + 100 - 8, High32(value), hexBase, digits - 8); + } + else { + if (digits < 1) + digits = 1; + ptr = Int32ToHexChars(buffer + 100, Low32(value), hexBase, digits); + } + + formatter.Append(ptr, (int)(buffer + 100 - ptr)); + } + + static char* Int32ToDecChars (char* p, uint value, int digits) { + while (value != 0) { + *--p = (char)(value % 10 + '0'); + value /= 10; + digits--; + } + + while (--digits >= 0) + *--p = '0'; + return p; + } + + static char* Int32ToHexChars (char* p, uint value, int hexBase, int digits) { + while (--digits >= 0 || value != 0) { + var digit = value & 0xF; + *--p = (char)(digit + (digit < 10 ? '0' : hexBase)); + value >>= 4; + } + return p; + } + + static char ParseFormatSpecifier (StringView specifier, out int digits) { + if (specifier.IsEmpty) { + digits = -1; + return 'G'; + } + + char* curr = specifier.Data; + char first = *curr++; + if ((first >= 'A' && first <= 'Z') || (first >= 'a' && first <= 'z')) { + int n = -1; + char c = *curr++; + if (c >= '0' && c <= '9') { + n = c - '0'; + c = *curr++; + while (c >= '0' && c <= '9') { + n = n * 10 + c - '0'; + c = *curr++; + if (n >= 10) + break; + } + } + + if (c == 0) { + digits = n; + return first; + } + } + + digits = -1; + return (char)0; + } + + static void Int32ToNumber (int value, ref Number number) { + number.Precision = Int32Precision; + if (value >= 0) + number.Sign = 0; + else { + number.Sign = 1; + value = -value; + } + + var buffer = stackalloc char[Int32Precision + 1]; + var ptr = Int32ToDecChars(buffer + Int32Precision, (uint)value, 0); + var len = (int)(buffer + Int32Precision - ptr); + number.Scale = len; + + var dest = number.Digits; + while (--len >= 0) + *dest++ = *ptr++; + *dest = '\0'; + } + + static void UInt32ToNumber (uint value, ref Number number) { + number.Precision = UInt32Precision; + number.Sign = 0; + + var buffer = stackalloc char[UInt32Precision + 1]; + var ptr = Int32ToDecChars(buffer + UInt32Precision, value, 0); + var len = (int)(buffer + UInt32Precision - ptr); + number.Scale = len; + + var dest = number.Digits; + while (--len >= 0) + *dest++ = *ptr++; + *dest = '\0'; + } + + static void Int64ToNumber (long value, ref Number number) { + number.Precision = Int64Precision; + if (value >= 0) + number.Sign = 0; + else { + number.Sign = 1; + value = -value; + } + + var buffer = stackalloc char[Int64Precision + 1]; + var ptr = buffer + Int64Precision; + var uv = (ulong)value; + while (High32(uv) != 0) + ptr = Int32ToDecChars(ptr, Int64DivMod(ref uv), 9); + + ptr = Int32ToDecChars(ptr, Low32(uv), 0); + var len = (int)(buffer + Int64Precision - ptr); + number.Scale = len; + + var dest = number.Digits; + while (--len >= 0) + *dest++ = *ptr++; + *dest = '\0'; + } + + static void UInt64ToNumber (ulong value, ref Number number) { + number.Precision = UInt64Precision; + number.Sign = 0; + + var buffer = stackalloc char[UInt64Precision + 1]; + var ptr = buffer + UInt64Precision; + while (High32(value) != 0) + ptr = Int32ToDecChars(ptr, Int64DivMod(ref value), 9); + + ptr = Int32ToDecChars(ptr, Low32(value), 0); + + var len = (int)(buffer + UInt64Precision - ptr); + number.Scale = len; + + var dest = number.Digits; + while (--len >= 0) + *dest++ = *ptr++; + *dest = '\0'; + } + + static void DoubleToNumber (double value, int precision, ref Number number) { + number.Precision = precision; + + uint sign, exp, mantHi, mantLo; + ExplodeDouble(value, out sign, out exp, out mantHi, out mantLo); + + if (exp == 0x7FF) { + // special value handling (infinity and NaNs) + number.Scale = (mantLo != 0 || mantHi != 0) ? ScaleNaN : ScaleInf; + number.Sign = (int)sign; + number.Digits[0] = '\0'; + } + else { + // convert the digits of the number to characters + if (value < 0) { + number.Sign = 1; + value = -value; + } + + var digits = number.Digits; + var end = digits + MaxFloatingDigits; + var p = end; + var shift = 0; + double intPart; + double reducedInt; + var fracPart = ModF(value, out intPart); + + if (intPart != 0) { + // format the integer part + while (intPart != 0) { + reducedInt = ModF(intPart / 10, out intPart); + *--p = (char)((int)((reducedInt + 0.03) * 10) + '0'); + shift++; + } + while (p < end) + *digits++ = *p++; + } + else if (fracPart > 0) { + // normalize the fractional part + while ((reducedInt = fracPart * 10) < 1) { + fracPart = reducedInt; + shift--; + } + } + + // concat the fractional part, padding the remainder with zeros + p = number.Digits + precision; + while (digits <= p && digits < end) { + fracPart *= 10; + fracPart = ModF(fracPart, out reducedInt); + *digits++ = (char)((int)reducedInt + '0'); + } + + // round the result if necessary + digits = p; + *p = (char)(*p + 5); + while (*p > '9') { + *p = '0'; + if (p > number.Digits) + ++*--p; + else { + *p = '1'; + shift++; + } + } + + number.Scale = shift; + *digits = '\0'; + } + } + + static void DecimalToNumber (uint* value, ref Number number) { + // bit 31 of the decimal is the sign bit + // bits 16-23 contain the scale + number.Sign = (int)(*value >> 31); + number.Scale = (int)((*value >> 16) & 0xFF); + number.Precision = DecimalPrecision; + + // loop for as long as the decimal is larger than 32 bits + var buffer = stackalloc char[DecimalPrecision + 1]; + var p = buffer + DecimalPrecision; + var hi = *(value + 1); + var lo = *(value + 2); + var mid = *(value + 3); + + while ((mid | hi) != 0) { + // keep dividing down by one billion at a time + ulong n = hi; + hi = (uint)(n / OneBillion); + n = (n % OneBillion) << 32 | mid; + mid = (uint)(n / OneBillion); + n = (n % OneBillion) << 32 | lo; + lo = (uint)(n / OneBillion); + + // format this portion of the number + p = Int32ToDecChars(p, (uint)(n % OneBillion), 9); + } + + // finish off with the low 32-bits of the decimal, if anything is left over + p = Int32ToDecChars(p, lo, 0); + + var len = (int)(buffer + DecimalPrecision - p); + number.Scale = len - number.Scale; + + var dest = number.Digits; + while (--len >= 0) + *dest++ = *p++; + *dest = '\0'; + } + + static void RoundNumber (ref Number number, int pos) { + var digits = number.Digits; + int i = 0; + while (i < pos && digits[i] != 0) i++; + if (i == pos && digits[i] >= '5') { + while (i > 0 && digits[i - 1] == '9') i--; + if (i > 0) + digits[i - 1]++; + else { + number.Scale++; + digits[0] = '1'; + i = 1; + } + } + else { + while (i > 0 && digits[i - 1] == '0') + i--; + } + + if (i == 0) { + number.Scale = 0; + number.Sign = 0; + } + + digits[i] = '\0'; + } + + static void AppendString (char** buffer, string value) { + fixed (char* pinnedString = value) + { + var length = value.Length; + for (var src = pinnedString; src < pinnedString + length; (*buffer)++, src++) + **buffer = *src; + } + } + + static int StrLen (char* str) { + int count = 0; + while (*str++ != 0) + count++; + + return count; + } + + static uint Int64DivMod (ref ulong value) { + var rem = (uint)(value % 1000000000); + value /= 1000000000; + return rem; + } + + static double ModF (double value, out double intPart) { + intPart = Math.Truncate(value); + return value - intPart; + } + + static void ExplodeDouble (double value, out uint sign, out uint exp, out uint mantHi, out uint mantLo) { + var bits = *(ulong*)&value; + if (BitConverter.IsLittleEndian) { + mantLo = (uint)(bits & 0xFFFFFFFF); // bits 0 - 31 + mantHi = (uint)((bits >> 32) & 0xFFFFF); // bits 32 - 51 + exp = (uint)((bits >> 52) & 0x7FF); // bits 52 - 62 + sign = (uint)((bits >> 63) & 0x1); // bit 63 + } + else { + sign = (uint)(bits & 0x1); // bit 0 + exp = (uint)((bits >> 1) & 0x7FF); // bits 1 - 11 + mantHi = (uint)((bits >> 12) & 0xFFFFF); // bits 12 - 31 + mantLo = (uint)(bits >> 32); // bits 32 - 63 + } + } + + static uint Low32 (ulong value) { + return (uint)value; + } + + static uint High32 (ulong value) { + return (uint)((value & 0xFFFFFFFF00000000) >> 32); + } + + struct Number { + public int Precision; + public int Scale; + public int Sign; + public char* Digits; + + // useful for debugging + public override string ToString () { + return new string(Digits); + } + } + + const int MaxNumberDigits = 50; + const int MaxFloatingDigits = 352; + const int Int32Precision = 10; + const int UInt32Precision = 10; + const int Int64Precision = 19; + const int UInt64Precision = 20; + const int FloatPrecision = 7; + const int DoublePrecision = 15; + const int DecimalPrecision = 29; + const int ScaleNaN = unchecked((int)0x80000000); + const int ScaleInf = 0x7FFFFFFF; + const int OneBillion = 1000000000; + } +} diff --git a/REPOSoftTechUtils/StringFormatter/Properties/AssemblyInfo.cs b/REPOSoftTechUtils/StringFormatter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b50b797 --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/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("StringFormatter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("StringFormatter")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("8a0ef787-605f-44ba-ae5c-d616451f8724")] + +// 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/REPOSoftTechUtils/StringFormatter/SR.cs b/REPOSoftTechUtils/StringFormatter/SR.cs new file mode 100644 index 0000000..f9fa2ef --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/SR.cs @@ -0,0 +1,11 @@ + +namespace System.Text.Formatting { + // currently just contains some hardcoded exception messages + static class SR { + public const string InvalidGroupSizes = "Invalid group sizes in NumberFormatInfo."; + public const string UnknownFormatSpecifier = "Unknown format specifier '{0}'."; + public const string ArgIndexOutOfRange = "No format argument exists for index '{0}'."; + public const string TypeNotFormattable = "Type '{0}' is not a built-in type, does not implement IStringFormattable, and no custom formatter was found for it."; + public const string InvalidFormatString = "Invalid format string."; + } +} diff --git a/REPOSoftTechUtils/StringFormatter/StringBuffer.cs b/REPOSoftTechUtils/StringFormatter/StringBuffer.cs new file mode 100644 index 0000000..7dfeba4 --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/StringBuffer.cs @@ -0,0 +1,685 @@ +using System.Globalization; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace System.Text.Formatting { + /// + /// Specifies an interface for types that act as a set of formatting arguments. + /// + public interface IArgSet { + /// + /// The number of arguments in the set. + /// + int Count { get; } + + /// + /// Format one of the arguments in the set into the given string buffer. + /// + /// The buffer to which to append the argument. + /// The index of the argument to format. + /// A specifier indicating how the argument should be formatted. + void Format (StringBuffer buffer, int index, StringView format); + } + + /// + /// Defines an interface for types that can be formatted into a string buffer. + /// + public interface IStringFormattable { + /// + /// Format the current instance into the given string buffer. + /// + /// The buffer to which to append. + /// A specifier indicating how the argument should be formatted. + void Format (StringBuffer buffer, StringView format); + } + + /// + /// A low-allocation version of the built-in type. + /// + public unsafe sealed partial class StringBuffer { + CachedCulture culture; + char[] buffer; + int currentCount; + + /// + /// The number of characters in the buffer. + /// + public int Count { + get { return currentCount; } + } + + /// + /// The culture used to format string data. + /// + public CultureInfo Culture { + get { return culture.Culture; } + set { + if (culture.Culture == value) + return; + + if (value == CultureInfo.InvariantCulture) + culture = CachedInvariantCulture; + else if (value == CachedCurrentCulture.Culture) + culture = CachedCurrentCulture; + else + culture = new CachedCulture(value); + } + } + + /// + /// Initializes a new instance of the class. + /// + public StringBuffer () + : this(DefaultCapacity) { + } + + /// + /// Initializes a new instance of the class. + /// + /// The initial size of the string buffer. + public StringBuffer (int capacity) { + buffer = new char[capacity]; + culture = CachedCurrentCulture; + } + + /// + /// Sets a custom formatter to use when converting instances of a given type to a string. + /// + /// The type for which to set the formatter. + /// A delegate that will be called to format instances of the specified type. + public static void SetCustomFormatter(Action formatter) { + ValueHelper.Formatter = formatter; + } + + /// + /// Clears the buffer. + /// + public void Clear () { + currentCount = 0; + } + + /// + /// Copies the contents of the buffer to the given array. + /// + /// The index within the buffer to begin copying. + /// The destination array. + /// The index within the destination array to which to begin copying. + /// The number of characters to copy. + public void CopyTo (int sourceIndex, char[] destination, int destinationIndex, int count) { + if (destination == null) + throw new ArgumentNullException(nameof(destination)); + if (destinationIndex + count > destination.Length || destinationIndex < 0) + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + + fixed (char* destPtr = &destination[destinationIndex]) + CopyTo(destPtr, sourceIndex, count); + } + + /// + /// Copies the contents of the buffer to the given array. + /// + /// A pointer to the destination array. + /// The index within the buffer to begin copying. + /// The number of characters to copy. + public void CopyTo (char* dest, int sourceIndex, int count) { + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count)); + if (sourceIndex + count > currentCount || sourceIndex < 0) + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + + fixed (char* s = buffer) + { + var src = s + sourceIndex; + for (int i = 0; i < count; i++) + *dest++ = *src++; + } + } + + /// + /// Copies the contents of the buffer to the given byte array. + /// + /// A pointer to the destination byte array. + /// The index within the buffer to begin copying. + /// The number of characters to copy. + /// The encoding to use to convert characters to bytes. + /// The number of bytes written to the destination. + public int CopyTo (byte* dest, int sourceIndex, int count, Encoding encoding) { + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count)); + if (sourceIndex + count > currentCount || sourceIndex < 0) + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + if (encoding == null) + throw new ArgumentNullException(nameof(encoding)); + + fixed (char* s = buffer) + return encoding.GetBytes(s, count, dest, count); + } + + /// + /// Converts the buffer to a string instance. + /// + /// A new string representing the characters currently in the buffer. + public override string ToString () { + return new string(buffer, 0, currentCount); + } + + /// + /// Appends a character to the current buffer. + /// + /// The character to append. + public void Append (char c) { + Append(c, 1); + } + + /// + /// Appends a character to the current buffer several times. + /// + /// The character to append. + /// The number of times to append the character. + public void Append (char c, int count) { + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count)); + + CheckCapacity(count); + fixed (char* b = &buffer[currentCount]) + { + var ptr = b; + for (int i = 0; i < count; i++) + *ptr++ = c; + currentCount += count; + } + } + + /// + /// Appends the specified string to the current buffer. + /// + /// The value to append. + public void Append (string value) { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + Append(value, 0, value.Length); + } + + /// + /// Appends a string subset to the current buffer. + /// + /// The string to append. + /// The starting index within the string to begin reading characters. + /// The number of characters to append. + public void Append (string value, int startIndex, int count) { + if (value == null) + throw new ArgumentNullException(nameof(value)); + if (startIndex < 0 || startIndex + count > value.Length) + throw new ArgumentOutOfRangeException(nameof(startIndex)); + + fixed (char* s = value) + Append(s + startIndex, count); + } + + /// + /// Appends an array of characters to the current buffer. + /// + /// The characters to append. + /// The starting index within the array to begin reading characters. + /// The number of characters to append. + public void Append (char[] values, int startIndex, int count) { + if (values == null) + throw new ArgumentNullException(nameof(values)); + if (startIndex < 0 || startIndex + count > values.Length) + throw new ArgumentOutOfRangeException(nameof(startIndex)); + + fixed (char* s = &values[startIndex]) + Append(s, count); + } + + /// + /// Appends an array of characters to the current buffer. + /// + /// A pointer to the array of characters to append. + /// The number of characters to append. + public void Append (char* str, int count) { + CheckCapacity(count); + fixed (char* b = &buffer[currentCount]) + { + var dest = b; + for (int i = 0; i < count; i++) + *dest++ = *str++; + currentCount += count; + } + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + public void Append (bool value) { + if (value) + Append(TrueLiteral); + else + Append(FalseLiteral); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (sbyte value, StringView format) { + Numeric.FormatSByte(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (byte value, StringView format) { + // widening here is fine + Numeric.FormatUInt32(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (short value, StringView format) { + Numeric.FormatInt16(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (ushort value, StringView format) { + // widening here is fine + Numeric.FormatUInt32(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (int value, StringView format) { + Numeric.FormatInt32(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (uint value, StringView format) { + Numeric.FormatUInt32(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (long value, StringView format) { + Numeric.FormatInt64(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (ulong value, StringView format) { + Numeric.FormatUInt64(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (float value, StringView format) { + Numeric.FormatSingle(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (double value, StringView format) { + Numeric.FormatDouble(this, value, format, culture); + } + + /// + /// Appends the specified value as a string to the current buffer. + /// + /// The value to append. + /// A format specifier indicating how to convert to a string. + public void Append (decimal value, StringView format) { + Numeric.FormatDecimal(this, (uint*)&value, format, culture); + } + + /// + /// Appends the string returned by processing a composite format string, which contains zero or more format items, to this instance. + /// Each format item is replaced by the string representation of a single argument. + /// + /// The type of argument set being formatted. + /// A composite format string. + /// The set of args to insert into the format string. + public void AppendArgSet(string format, ref T args) where T : IArgSet { + if (format == null) + throw new ArgumentNullException(nameof(format)); + + fixed (char* formatPtr = format) + { + var curr = formatPtr; + var end = curr + format.Length; + var segmentsLeft = false; + var prevArgIndex = 0; + do { + CheckCapacity((int)(end - curr)); + fixed (char* bufferPtr = &buffer[currentCount]) + segmentsLeft = AppendSegment(ref curr, end, bufferPtr, ref prevArgIndex, ref args); + } + while (segmentsLeft); + } + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + void CheckCapacity (int count) { + if (currentCount + count > buffer.Length) + Array.Resize(ref buffer, buffer.Length * 2); + } + + bool AppendSegment(ref char* currRef, char* end, char* dest, ref int prevArgIndex, ref T args) where T : IArgSet { + char* curr = currRef; + char c = '\x0'; + while (curr < end) { + c = *curr++; + if (c == '}') { + // check for escape character for }} + if (curr < end && *curr == '}') + curr++; + else + ThrowError(); + } + else if (c == '{') { + // check for escape character for {{ + if (curr == end) + ThrowError(); + else if (*curr == '{') + curr++; + else + break; + } + + *dest++ = c; + currentCount++; + } + + if (curr == end) + return false; + + int index; + if (*curr == '}') + index = prevArgIndex; + else + index = ParseNum(ref curr, end, MaxArgs); + if (index >= args.Count) + throw new FormatException(string.Format(SR.ArgIndexOutOfRange, index)); + + // check for a spacing specifier + c = SkipWhitespace(ref curr, end); + var width = 0; + var leftJustify = false; + var oldCount = currentCount; + if (c == ',') { + curr++; + c = SkipWhitespace(ref curr, end); + + // spacing can be left-justified + if (c == '-') { + leftJustify = true; + curr++; + if (curr == end) + ThrowError(); + } + + width = ParseNum(ref curr, end, MaxSpacing); + c = SkipWhitespace(ref curr, end); + } + + // check for format specifier + curr++; + if (c == ':') { + var specifierBuffer = stackalloc char[MaxSpecifierSize]; + var specifierEnd = specifierBuffer + MaxSpecifierSize; + var specifierPtr = specifierBuffer; + + while (true) { + if (curr == end) + ThrowError(); + + c = *curr++; + if (c == '{') { + // check for escape character for {{ + if (curr < end && *curr == '{') + curr++; + else + ThrowError(); + } + else if (c == '}') { + // check for escape character for }} + if (curr < end && *curr == '}') + curr++; + else { + // found the end of the specifier + // kick off the format job + var specifier = new StringView(specifierBuffer, (int)(specifierPtr - specifierBuffer)); + args.Format(this, index, specifier); + break; + } + } + + if (specifierPtr == specifierEnd) + ThrowError(); + *specifierPtr++ = c; + } + } + else { + // no specifier. make sure we're at the end of the format block + if (c != '}') + ThrowError(); + + // format without any specifier + args.Format(this, index, StringView.Empty); + } + + // finish off padding, if necessary + var padding = width - (currentCount - oldCount); + if (padding > 0) { + if (leftJustify) + Append(' ', padding); + else { + // copy the recently placed chars up in memory to make room for padding + CheckCapacity(padding); + for (int i = currentCount - 1; i >= oldCount; i--) + buffer[i + padding] = buffer[i]; + + // fill in padding + for (int i = 0; i < padding; i++) + buffer[i + oldCount] = ' '; + currentCount += padding; + } + } + + prevArgIndex = index + 1; + currRef = curr; + return true; + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void AppendGeneric(IntPtr ptr, StringView format) { + // ptr here is a pointer to the parameter we want to format; for + // simple value types we can cast the pointer directly, but for + // strings and unknown generic value types we need to pull them + // out via a typed reference + + // this looks gross, but T is known at JIT-time so this call tree + // gets compiled down to a direct call with no branching + if (typeof(T) == typeof(sbyte)) + Append(*(sbyte*)ptr, format); + else if (typeof(T) == typeof(byte)) + Append(*(byte*)ptr, format); + else if (typeof(T) == typeof(short)) + Append(*(short*)ptr, format); + else if (typeof(T) == typeof(ushort)) + Append(*(ushort*)ptr, format); + else if (typeof(T) == typeof(int)) + Append(*(int*)ptr, format); + else if (typeof(T) == typeof(uint)) + Append(*(uint*)ptr, format); + else if (typeof(T) == typeof(long)) + Append(*(long*)ptr, format); + else if (typeof(T) == typeof(ulong)) + Append(*(ulong*)ptr, format); + else if (typeof(T) == typeof(float)) + Append(*(float*)ptr, format); + else if (typeof(T) == typeof(double)) + Append(*(double*)ptr, format); + else if (typeof(T) == typeof(decimal)) + Append(*(decimal*)ptr, format); + else if (typeof(T) == typeof(bool)) + Append(*(bool*)ptr); + else if (typeof(T) == typeof(char)) + Append(*(char*)ptr, format); + else if (typeof(T) == typeof(string)) { + var placeholder = default(T); + var tr = __makeref(placeholder); + *(IntPtr*)&tr = ptr; + Append(__refvalue(tr, string)); + } + else { + // otherwise, we have an unknown type; extract it from the pointer + var placeholder = default(T); + var tr = __makeref(placeholder); + *(IntPtr*)&tr = ptr; + var value = __refvalue(tr, T); + + // first, check to see if it's a value type implementing IStringFormattable + var formatter = ValueHelper.Formatter; + if (formatter != null) + formatter(this, value, format); + else { + // Only two cases left; reference type implementing IStringFormattable, + // or some unknown type that doesn't implement the interface at all. + // We could handle the latter case by calling ToString() on it and paying the + // allocation, but presumably if the user is using us instead of the built-in + // formatting utilities they would rather be notified of this case, so + // we'll let the cast throw. + var formattable = value as IStringFormattable; + if (formattable == null) + throw new InvalidOperationException(string.Format(SR.TypeNotFormattable, typeof(T))); + formattable.Format(this, format); + } + } + } + + static int ParseNum (ref char* currRef, char* end, int maxValue) { + char* curr = currRef; + char c = *curr; + if (c < '0' || c > '9') + ThrowError(); + + int value = 0; + do { + value = value * 10 + c - '0'; + curr++; + if (curr == end) + ThrowError(); + c = *curr; + } while (c >= '0' && c <= '9' && value < maxValue); + + currRef = curr; + return value; + } + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + static char SkipWhitespace (ref char* currRef, char* end) { + char* curr = currRef; + while (curr < end && *curr == ' ') curr++; + + if (curr == end) + ThrowError(); + + currRef = curr; + return *curr; + } + + static void ThrowError () { + throw new FormatException(SR.InvalidFormatString); + } + + static StringBuffer Acquire (int capacity) { + if (capacity <= MaxCachedSize) { + var buffer = CachedInstance; + if (buffer != null) { + CachedInstance = null; + buffer.Clear(); + buffer.CheckCapacity(capacity); + return buffer; + } + } + + return new StringBuffer(capacity); + } + + static void Release (StringBuffer buffer) { + if (buffer.buffer.Length <= MaxCachedSize) + CachedInstance = buffer; + } + + [ThreadStatic] + static StringBuffer CachedInstance; + + static readonly CachedCulture CachedInvariantCulture = new CachedCulture(CultureInfo.InvariantCulture); + static readonly CachedCulture CachedCurrentCulture = new CachedCulture(CultureInfo.CurrentCulture); + + const int DefaultCapacity = 32; + const int MaxCachedSize = 360; // same as BCL's StringBuilderCache + const int MaxArgs = 256; + const int MaxSpacing = 1000000; + const int MaxSpecifierSize = 32; + + const string TrueLiteral = "True"; + const string FalseLiteral = "False"; + + // The point of this class is to allow us to generate a direct call to a known + // method on an unknown, unconstrained generic value type. Normally this would + // be impossible; you'd have to cast the generic argument and introduce boxing. + // Instead we pay a one-time startup cost to create a delegate that will forward + // the parameter to the appropriate method in a strongly typed fashion. + static class ValueHelper { + public static Action Formatter = Prepare(); + + static Action Prepare () { + // we only use this class for value types that also implement IStringFormattable + var type = typeof(T); + if (!type.IsValueType || !typeof(IStringFormattable).IsAssignableFrom(type)) + return null; + + var result = typeof(ValueHelper) + .GetMethod("Assign", BindingFlags.NonPublic | BindingFlags.Static) + .MakeGenericMethod(type) + .Invoke(null, null); + return (Action)result; + } + + static Action Assign() where U : IStringFormattable { + return (f, u, v) => u.Format(f, v); + } + } + } +} \ No newline at end of file diff --git a/REPOSoftTechUtils/StringFormatter/StringFormatter.csproj b/REPOSoftTechUtils/StringFormatter/StringFormatter.csproj new file mode 100644 index 0000000..cd4b86e --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/StringFormatter.csproj @@ -0,0 +1,71 @@ + + + + + Debug + AnyCPU + {8A0EF787-605F-44BA-AE5C-D616451F8724} + Library + Properties + System.Text.Formatting + StringFormatter + v3.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + bin\Release\StringFormatter.XML + + + + + + + + True + True + Arg.tt + + + + + + + + + + + + TextTemplatingFileGenerator + Arg.cs + + + + + + + + \ No newline at end of file diff --git a/REPOSoftTechUtils/StringFormatter/StringView.cs b/REPOSoftTechUtils/StringFormatter/StringView.cs new file mode 100644 index 0000000..2f39d19 --- /dev/null +++ b/REPOSoftTechUtils/StringFormatter/StringView.cs @@ -0,0 +1,41 @@ + +namespace System.Text.Formatting { + // TODO: clean this up + public unsafe struct StringView { + public static readonly StringView Empty = new StringView(); + + public readonly char* Data; + public readonly int Length; + + public bool IsEmpty { + get { return Length == 0; } + } + + public StringView (char* data, int length) { + Data = data; + Length = length; + } + + public static bool operator ==(StringView lhs, string rhs) { + var count = lhs.Length; + if (count != rhs.Length) + return false; + + fixed (char* r = rhs) + { + var lhsPtr = lhs.Data; + var rhsPtr = r; + for (int i = 0; i < count; i++) { + if (*lhsPtr++ != *rhsPtr++) + return false; + } + } + + return true; + } + + public static bool operator !=(StringView lhs, string rhs) { + return !(lhs == rhs); + } + } +} diff --git a/REPOSoftTechUtils/ToolBarManager.cs b/REPOSoftTechUtils/ToolBarManager.cs new file mode 100644 index 0000000..e94826b --- /dev/null +++ b/REPOSoftTechUtils/ToolBarManager.cs @@ -0,0 +1,887 @@ +/* +Copyright (c) 2013-2014, Maik Schreiber +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace RSTUtils +{ + /**********************************************************\ + * --- DO NOT EDIT BELOW THIS COMMENT --- * + * * + * This file contains classes and interfaces to use the * + * Toolbar Plugin without creating a hard dependency on it. * + * * + * There is nothing in this file that needs to be edited * + * by hand. * + * * + * --- DO NOT EDIT BELOW THIS COMMENT --- * + \**********************************************************/ + + /// + /// The global tool bar manager. + /// + public partial class ToolbarManager : IToolbarManager + { + /// + /// Whether the Toolbar Plugin is available. + /// + public static bool ToolbarAvailable + { + get + { + if (toolbarAvailable == null) + { + toolbarAvailable = Instance != null; + } + return (bool)toolbarAvailable; + } + } + + /// + /// The global tool bar manager instance. + /// + public static IToolbarManager Instance + { + get + { + if ((toolbarAvailable != false) && (instance_ == null)) + { + Type type = ToolbarTypes.getType("Toolbar.ToolbarManager"); + if (type != null) + { + object realToolbarManager = ToolbarTypes.getStaticProperty(type, "Instance").GetValue(null, null); + instance_ = new ToolbarManager(realToolbarManager); + } + } + return instance_; + } + } + } + + #region interfaces + + /// + /// A toolbar manager. + /// + public interface IToolbarManager + { + /// + /// Adds a new button. + /// + /// + /// To replace an existing button, just add a new button using the old button's namespace and ID. + /// Note that the new button will inherit the screen position of the old button. + /// + /// The new button's namespace. This is usually the plugin's name. Must not include special characters like '.' + /// The new button's ID. This ID must be unique across all buttons in the namespace. Must not include special characters like '.' + /// The button created. + IButton add(string ns, string id); + } + + /// + /// Represents a clickable button. + /// + public interface IButton + { + /// + /// The text displayed on the button. Set to null to hide text. + /// + /// + /// The text can be changed at any time to modify the button's appearance. Note that since this will also + /// modify the button's size, this feature should be used sparingly, if at all. + /// + /// + string Text + { + set; + get; + } + + /// + /// The color the button text is displayed with. Defaults to Color.white. + /// + /// + /// The text color can be changed at any time to modify the button's appearance. + /// + Color TextColor + { + set; + get; + } + + /// + /// The path of a texture file to display an icon on the button. Set to null to hide icon. + /// + /// + /// + /// A texture path on a button will have precedence over text. That is, if both text and texture path + /// have been set on a button, the button will show the texture, not the text. + /// + /// + /// The texture size must not exceed 24x24 pixels. + /// + /// + /// The texture path must be relative to the "GameData" directory, and must not specify a file name suffix. + /// Valid example: MyAddon/Textures/icon_mybutton + /// + /// + /// The texture path can be changed at any time to modify the button's appearance. + /// + /// + /// + string TexturePath + { + set; + get; + } + + /// + /// The button's tool tip text. Set to null if no tool tip is desired. + /// + /// + /// Tool Tip Text Should Always Use Headline Style Like This. + /// + string ToolTip + { + set; + get; + } + + /// + /// Whether this button is currently visible or not. Can be used in addition to or as a replacement for . + /// + /// + /// Setting this property to true does not affect the player's ability to hide the button using the configuration. + /// Conversely, setting this property to false does not enable the player to show the button using the configuration. + /// + bool Visible + { + set; + get; + } + + /// + /// Determines this button's visibility. Can be used in addition to or as a replacement for . + /// + /// + /// The return value from IVisibility.Visible is subject to the same rules as outlined for + /// . + /// + IVisibility Visibility + { + set; + get; + } + + /// + /// Whether this button is currently effectively visible or not. This is a combination of + /// and . + /// + /// + /// Note that the toolbar is not visible in certain game scenes, for example the loading screens. This property + /// does not reflect button invisibility in those scenes. In addition, this property does not reflect the + /// player's configuration of the button's visibility. + /// + bool EffectivelyVisible + { + get; + } + + /// + /// Whether this button is currently enabled (clickable) or not. This does not affect the player's ability to + /// position the button on their toolbar. + /// + bool Enabled + { + set; + get; + } + + /// + /// Whether this button is currently "important." Set to false to return to normal button behaviour. + /// + /// + /// + /// This can be used to temporarily force the button to be shown on screen regardless of the toolbar being + /// currently in auto-hidden mode. For example, a button that signals the arrival of a private message in + /// a chat room could mark itself as "important" as long as the message has not been read. + /// + /// + /// Setting this property does not change the appearance of the button. Use to + /// change the button's icon. + /// + /// + /// Setting this property to true does not affect the player's ability to hide the button using the + /// configuration. + /// + /// + /// This feature should be used only sparingly, if at all, since it forces the button to be displayed on + /// screen even when it normally wouldn't. + /// + /// + bool Important + { + set; + get; + } + + /// + /// A drawable that is tied to the current button. This can be anything from a popup menu to + /// an informational window. Set to null to hide the drawable. + /// + IDrawable Drawable + { + set; + get; + } + + /// + /// Event handler that can be registered with to receive "on click" events. + /// + /// + /// + /// IButton button = ... + /// button.OnClick += (e) => { + /// Debug.Log("button clicked, mouseButton: " + e.MouseButton); + /// }; + /// + /// + event ClickHandler OnClick; + + /// + /// Event handler that can be registered with to receive "on mouse enter" events. + /// + /// + /// + /// IButton button = ... + /// button.OnMouseEnter += (e) => { + /// Debug.Log("mouse entered button"); + /// }; + /// + /// + event MouseEnterHandler OnMouseEnter; + + /// + /// Event handler that can be registered with to receive "on mouse leave" events. + /// + /// + /// + /// IButton button = ... + /// button.OnMouseLeave += (e) => { + /// Debug.Log("mouse left button"); + /// }; + /// + /// + event MouseLeaveHandler OnMouseLeave; + + /// + /// Permanently destroys this button so that it is no longer displayed. + /// Should be used when a plugin is stopped to remove leftover buttons. + /// + void Destroy(); + } + + /// + /// A drawable that is tied to a particular button. This can be anything from a popup menu + /// to an informational window. + /// + public interface IDrawable + { + /// + /// Update any information. This is called once per frame. + /// + void Update(); + + /// + /// Draws GUI widgets for this drawable. This is the equivalent to the OnGUI() message in + /// . + /// + /// + /// The drawable will be positioned near its parent toolbar according to the drawable's current + /// width/height. + /// + /// The left/top position of where to draw this drawable. + /// The current width/height of this drawable. + Vector2 Draw(Vector2 position); + } + + #endregion interfaces + + #region events + + /// + /// Event describing a click on a button. + /// + public partial class ClickEvent : EventArgs + { + /// + /// The button that has been clicked. + /// + public readonly IButton Button; + + /// + /// The mouse button which the button was clicked with. + /// + /// + /// Is 0 for left mouse button, 1 for right mouse button, and 2 for middle mouse button. + /// + public readonly int MouseButton; + } + + /// + /// An event handler that is invoked whenever a button has been clicked. + /// + /// An event describing the button click. + public delegate void ClickHandler(ClickEvent e); + + /// + /// Event describing the mouse pointer moving about a button. + /// + public abstract partial class MouseMoveEvent + { + /// + /// The button in question. + /// + public readonly IButton button; + } + + /// + /// Event describing the mouse pointer entering a button's area. + /// + public partial class MouseEnterEvent : MouseMoveEvent + { + } + + /// + /// Event describing the mouse pointer leaving a button's area. + /// + public partial class MouseLeaveEvent : MouseMoveEvent + { + } + + /// + /// An event handler that is invoked whenever the mouse pointer enters a button's area. + /// + /// An event describing the mouse pointer entering. + public delegate void MouseEnterHandler(MouseEnterEvent e); + + /// + /// An event handler that is invoked whenever the mouse pointer leaves a button's area. + /// + /// An event describing the mouse pointer leaving. + public delegate void MouseLeaveHandler(MouseLeaveEvent e); + + #endregion events + + #region visibility + + /// + /// Determines visibility of a button. + /// + /// + public interface IVisibility + { + /// + /// Whether a button is currently visible or not. + /// + /// + bool Visible + { + get; + } + } + + /// + /// Determines visibility of a button in relation to the currently running game scene. + /// + /// + /// + /// IButton button = ... + /// button.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.SPH); + /// + /// + /// + public class GameScenesVisibility : IVisibility + { + public bool Visible + { + get + { + return (bool)visibleProperty.GetValue(realGameScenesVisibility, null); + } + } + + private object realGameScenesVisibility; + private PropertyInfo visibleProperty; + + public GameScenesVisibility(params GameScenes[] gameScenes) + { + Type gameScenesVisibilityType = ToolbarTypes.getType("Toolbar.GameScenesVisibility"); + realGameScenesVisibility = Activator.CreateInstance(gameScenesVisibilityType, gameScenes); + visibleProperty = ToolbarTypes.getProperty(gameScenesVisibilityType, "Visible"); + } + } + + #endregion visibility + + #region drawable + + /// + /// A drawable that draws a popup menu. + /// + public class PopupMenuDrawable : IDrawable + { + /// + /// Event handler that can be registered with to receive "any menu option clicked" events. + /// + public event Action OnAnyOptionClicked + { + add + { + onAnyOptionClickedEvent.AddEventHandler(realPopupMenuDrawable, value); + } + remove + { + onAnyOptionClickedEvent.RemoveEventHandler(realPopupMenuDrawable, value); + } + } + + private object realPopupMenuDrawable; + private MethodInfo updateMethod; + private MethodInfo drawMethod; + private MethodInfo addOptionMethod; + private MethodInfo addSeparatorMethod; + private MethodInfo destroyMethod; + private EventInfo onAnyOptionClickedEvent; + + public PopupMenuDrawable() + { + Type popupMenuDrawableType = ToolbarTypes.getType("Toolbar.PopupMenuDrawable"); + realPopupMenuDrawable = Activator.CreateInstance(popupMenuDrawableType, null); + updateMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "Update"); + drawMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "Draw"); + addOptionMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "AddOption"); + addSeparatorMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "AddSeparator"); + destroyMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "Destroy"); + onAnyOptionClickedEvent = ToolbarTypes.getEvent(popupMenuDrawableType, "OnAnyOptionClicked"); + } + + public void Update() + { + updateMethod.Invoke(realPopupMenuDrawable, null); + } + + public Vector2 Draw(Vector2 position) + { + return (Vector2)drawMethod.Invoke(realPopupMenuDrawable, new object[] { position }); + } + + /// + /// Adds a new option to the popup menu. + /// + /// The text of the option. + /// A button that can be used to register clicks on the menu option. + public IButton AddOption(string text) + { + object realButton = addOptionMethod.Invoke(realPopupMenuDrawable, new object[] { text }); + return new Button(realButton, new ToolbarTypes()); + } + + /// + /// Adds a separator to the popup menu. + /// + public void AddSeparator() + { + addSeparatorMethod.Invoke(realPopupMenuDrawable, null); + } + + /// + /// Destroys this drawable. This must always be called before disposing of this drawable. + /// + public void Destroy() + { + destroyMethod.Invoke(realPopupMenuDrawable, null); + } + } + + #endregion drawable + + #region private implementations + + public partial class ToolbarManager : IToolbarManager + { + private static bool? toolbarAvailable; + private static IToolbarManager instance_; + private object realToolbarManager; + private MethodInfo addMethod; + private Dictionary buttons = new Dictionary(); + private ToolbarTypes types = new ToolbarTypes(); + + private ToolbarManager(object realToolbarManager) + { + this.realToolbarManager = realToolbarManager; + addMethod = ToolbarTypes.getMethod(types.iToolbarManagerType, "add"); + } + + public IButton add(string ns, string id) + { + object realButton = addMethod.Invoke(realToolbarManager, new object[] { ns, id }); + IButton button = new Button(realButton, types); + buttons.Add(realButton, button); + return button; + } + } + + internal class Button : IButton + { + private object realButton; + private ToolbarTypes types; + private Delegate realClickHandler; + private Delegate realMouseEnterHandler; + private Delegate realMouseLeaveHandler; + + internal Button(object realButton, ToolbarTypes types) + { + this.realButton = realButton; + this.types = types; + realClickHandler = attachEventHandler(types.button.onClickEvent, "clicked", realButton); + realMouseEnterHandler = attachEventHandler(types.button.onMouseEnterEvent, "mouseEntered", realButton); + realMouseLeaveHandler = attachEventHandler(types.button.onMouseLeaveEvent, "mouseLeft", realButton); + } + + private Delegate attachEventHandler(EventInfo @event, string methodName, object realButton) + { + MethodInfo method = GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + Delegate d = Delegate.CreateDelegate(@event.EventHandlerType, this, method); + @event.AddEventHandler(realButton, d); + return d; + } + + public string Text + { + set + { + types.button.textProperty.SetValue(realButton, value, null); + } + get + { + return (string)types.button.textProperty.GetValue(realButton, null); + } + } + + public Color TextColor + { + set + { + types.button.textColorProperty.SetValue(realButton, value, null); + } + get + { + return (Color)types.button.textColorProperty.GetValue(realButton, null); + } + } + + public string TexturePath + { + set + { + types.button.texturePathProperty.SetValue(realButton, value, null); + } + get + { + return (string)types.button.texturePathProperty.GetValue(realButton, null); + } + } + + public string ToolTip + { + set + { + types.button.toolTipProperty.SetValue(realButton, value, null); + } + get + { + return (string)types.button.toolTipProperty.GetValue(realButton, null); + } + } + + public bool Visible + { + set + { + types.button.visibleProperty.SetValue(realButton, value, null); + } + get + { + return (bool)types.button.visibleProperty.GetValue(realButton, null); + } + } + + public IVisibility Visibility + { + set + { + object functionVisibility = null; + if (value != null) + { + functionVisibility = Activator.CreateInstance(types.functionVisibilityType, new Func(() => value.Visible)); + } + types.button.visibilityProperty.SetValue(realButton, functionVisibility, null); + visibility_ = value; + } + get + { + return visibility_; + } + } + + private IVisibility visibility_; + + public bool EffectivelyVisible + { + get + { + return (bool)types.button.effectivelyVisibleProperty.GetValue(realButton, null); + } + } + + public bool Enabled + { + set + { + types.button.enabledProperty.SetValue(realButton, value, null); + } + get + { + return (bool)types.button.enabledProperty.GetValue(realButton, null); + } + } + + public bool Important + { + set + { + types.button.importantProperty.SetValue(realButton, value, null); + } + get + { + return (bool)types.button.importantProperty.GetValue(realButton, null); + } + } + + public IDrawable Drawable + { + set + { + object functionDrawable = null; + if (value != null) + { + functionDrawable = Activator.CreateInstance(types.functionDrawableType, new Action(value.Update), new Func(value.Draw)); + } + types.button.drawableProperty.SetValue(realButton, functionDrawable, null); + drawable_ = value; + } + get + { + return drawable_; + } + } + + private IDrawable drawable_; + + public event ClickHandler OnClick; + + private void clicked(object realEvent) + { + if (OnClick != null) + { + OnClick(new ClickEvent(realEvent, this)); + } + } + + public event MouseEnterHandler OnMouseEnter; + + private void mouseEntered(object realEvent) + { + if (OnMouseEnter != null) + { + OnMouseEnter(new MouseEnterEvent(this)); + } + } + + public event MouseLeaveHandler OnMouseLeave; + + private void mouseLeft(object realEvent) + { + if (OnMouseLeave != null) + { + OnMouseLeave(new MouseLeaveEvent(this)); + } + } + + public void Destroy() + { + detachEventHandler(types.button.onClickEvent, realClickHandler, realButton); + detachEventHandler(types.button.onMouseEnterEvent, realMouseEnterHandler, realButton); + detachEventHandler(types.button.onMouseLeaveEvent, realMouseLeaveHandler, realButton); + types.button.destroyMethod.Invoke(realButton, null); + } + + private void detachEventHandler(EventInfo @event, Delegate d, object realButton) + { + @event.RemoveEventHandler(realButton, d); + } + } + + public partial class ClickEvent : EventArgs + { + internal ClickEvent(object realEvent, IButton button) + { + Type type = realEvent.GetType(); + Button = button; + MouseButton = (int)type.GetField("MouseButton", BindingFlags.Public | BindingFlags.Instance).GetValue(realEvent); + } + } + + public abstract partial class MouseMoveEvent : EventArgs + { + internal MouseMoveEvent(IButton button) + { + this.button = button; + } + } + + public partial class MouseEnterEvent : MouseMoveEvent + { + internal MouseEnterEvent(IButton button) + : base(button) + { + } + } + + public partial class MouseLeaveEvent : MouseMoveEvent + { + internal MouseLeaveEvent(IButton button) + : base(button) + { + } + } + + internal class ToolbarTypes + { + internal readonly Type iToolbarManagerType; + internal readonly Type functionVisibilityType; + internal readonly Type functionDrawableType; + internal readonly ButtonTypes button; + + internal ToolbarTypes() + { + iToolbarManagerType = getType("Toolbar.IToolbarManager"); + functionVisibilityType = getType("Toolbar.FunctionVisibility"); + functionDrawableType = getType("Toolbar.FunctionDrawable"); + Type iButtonType = getType("Toolbar.IButton"); + button = new ButtonTypes(iButtonType); + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + internal static PropertyInfo getProperty(Type type, string name) + { + return type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance); + } + + internal static PropertyInfo getStaticProperty(Type type, string name) + { + return type.GetProperty(name, BindingFlags.Public | BindingFlags.Static); + } + + internal static EventInfo getEvent(Type type, string name) + { + return type.GetEvent(name, BindingFlags.Public | BindingFlags.Instance); + } + + internal static MethodInfo getMethod(Type type, string name) + { + return type.GetMethod(name, BindingFlags.Public | BindingFlags.Instance); + } + } + + internal class ButtonTypes + { + internal readonly Type iButtonType; + internal readonly PropertyInfo textProperty; + internal readonly PropertyInfo textColorProperty; + internal readonly PropertyInfo texturePathProperty; + internal readonly PropertyInfo toolTipProperty; + internal readonly PropertyInfo visibleProperty; + internal readonly PropertyInfo visibilityProperty; + internal readonly PropertyInfo effectivelyVisibleProperty; + internal readonly PropertyInfo enabledProperty; + internal readonly PropertyInfo importantProperty; + internal readonly PropertyInfo drawableProperty; + internal readonly EventInfo onClickEvent; + internal readonly EventInfo onMouseEnterEvent; + internal readonly EventInfo onMouseLeaveEvent; + internal readonly MethodInfo destroyMethod; + + internal ButtonTypes(Type iButtonType) + { + this.iButtonType = iButtonType; + textProperty = ToolbarTypes.getProperty(iButtonType, "Text"); + textColorProperty = ToolbarTypes.getProperty(iButtonType, "TextColor"); + texturePathProperty = ToolbarTypes.getProperty(iButtonType, "TexturePath"); + toolTipProperty = ToolbarTypes.getProperty(iButtonType, "ToolTip"); + visibleProperty = ToolbarTypes.getProperty(iButtonType, "Visible"); + visibilityProperty = ToolbarTypes.getProperty(iButtonType, "Visibility"); + effectivelyVisibleProperty = ToolbarTypes.getProperty(iButtonType, "EffectivelyVisible"); + enabledProperty = ToolbarTypes.getProperty(iButtonType, "Enabled"); + importantProperty = ToolbarTypes.getProperty(iButtonType, "Important"); + drawableProperty = ToolbarTypes.getProperty(iButtonType, "Drawable"); + onClickEvent = ToolbarTypes.getEvent(iButtonType, "OnClick"); + onMouseEnterEvent = ToolbarTypes.getEvent(iButtonType, "OnMouseEnter"); + onMouseLeaveEvent = ToolbarTypes.getEvent(iButtonType, "OnMouseLeave"); + destroyMethod = ToolbarTypes.getMethod(iButtonType, "Destroy"); + } + } + + #endregion private implementations +} \ No newline at end of file diff --git a/Source/APIs/DFGameEvents.cs b/Source/APIs/DFGameEvents.cs new file mode 100644 index 0000000..6c5bea1 --- /dev/null +++ b/Source/APIs/DFGameEvents.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DF +{ + class DFGameEvents + { + /// + /// Fires when DeepFreeze Starts the Freezing process on a Kerbal. + /// Part is the DeepFreeze Freezer Part and the string is the Kerbal name. + /// + public static EventData onKerbalFreezing; + /// + /// Fires when DeepFreeze Starts the Thawing process on a Kerbal. + /// Part is the DeepFreeze Freezer Part and the string is the Kerbal name. + /// + public static EventData onKerbalThawing; + /// + /// Fires when DeepFreeze Aborts a Thawing process on a Kerbal. + /// Part is the DeepFreeze Freezer Part and the string is the Kerbal name. + /// + public static EventData onKerbalThawAbort; + /// + /// Fires when DeepFreeze Aborts a Freezing process on a Kerbal. + /// Part is the DeepFreeze Freezer Part and the string is the Kerbal name. + /// + public static EventData onKerbalFreezeAbort; + /// + /// Fires when DeepFreeze Completes the Freezing process on a Kerbal. + /// Part is the DeepFreeze Freezer Part and ProtoCrewMember is the Kerbal. + /// + public static EventData onKerbalFrozen; + /// + /// Fires when DeepFreeze Completes the Thawing process on a Kerbal. + /// Part is the DeepFreeze Freezer Part and ProtoCrewMember is the Kerbal. + /// + public static EventData onKerbalThaw; + /// + /// Fires when DeepFreeze sets a Kerbal to Comatose Status. + /// Part is the DeepFreeze Freezer Part and ProtoCrewMember is the Kerbal. + /// + public static EventData onKerbalSetComatose; + /// + /// Fires when DeepFreeze Unsets a Kerbal from Comatose Status. + /// Part is the DeepFreeze Freezer Part and ProtoCrewMember is the Kerbal. + /// + public static EventData onKerbalUnSetComatose; + /// + /// Fires when DeepFreeze has to Kill a Frozen Kerbal. + /// + public static EventData onFrozenKerbalDied; + + } +} diff --git a/Source/APIs/DFWrapper.cs b/Source/APIs/DFWrapper.cs new file mode 100644 index 0000000..6dcd720 --- /dev/null +++ b/Source/APIs/DFWrapper.cs @@ -0,0 +1,1489 @@ +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_DFWrapper +{ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // 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 + { + internal static System.Type DFType; + internal static System.Type KerbalInfoType; + internal static System.Type VesselInfoType; + internal static System.Type PartInfoType; + internal static System.Type DeepFreezerType; + internal static System.Type FrznCrewMbrType; + internal 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; + DFType = null; + KerbalInfoType = null; + VesselInfoType = null; + PartInfoType = null; + DeepFreezerType = null; + FrznCrewMbrType = null; + LogFormatted("Attempting to Grab DeepFreeze Types..."); + + //find the base type + DFType = getType("DF.DeepFreeze"); + + if (DFType == null) + { + return false; + } + + LogFormatted("DeepFreeze Version:{0}", DFType.Assembly.GetName().Version.ToString()); + + //now the KerbalInfo Type + KerbalInfoType = getType("DF.KerbalInfo"); + + if (KerbalInfoType == null) + { + return false; + } + + //now the VesselInfo Type + VesselInfoType = getType("DF.VesselInfo"); + + if (VesselInfoType == null) + { + return false; + } + + //now the PartInfo Type + PartInfoType = getType("DF.PartInfo"); + + if (PartInfoType == null) + { + return false; + } + + //now the DeepFreezer (partmodule) Type + DeepFreezerType = getType("DF.DeepFreezer"); + + if (DeepFreezerType == null) + { + return false; + } + + //now the FrznCrewMbr Type + FrznCrewMbrType = getType("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; + } + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + /// + /// 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 KillFrozenCrew Method Object"); + ActualKillFrozenCrewMethod = DFType.GetMethod("KillFrozenCrew", BindingFlags.Public | BindingFlags.Instance); + LogFormatted("Success: " + (ActualKillFrozenCrewMethod != 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()); + + LogFormatted("Getting FrozenKerbals Object"); + FrozenKerbalsListMethod = DFType.GetMethod("get_FrozenKerbalsList", BindingFlags.Public | BindingFlags.Instance); + actualFrozenKerbalsList = FrozenKerbalsListMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualFrozenKerbalsList != null).ToString()); + + LogFormatted("Getting KnownVessels Object"); + knownVesselsMethod = DFType.GetMethod("get_KnownVessels", BindingFlags.Public | BindingFlags.Instance); + actualKnownVessels = knownVesselsMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualKnownVessels != null).ToString()); + + LogFormatted("Getting KnownVessels Object"); + knownVesselsListMethod = DFType.GetMethod("get_KnownVesselsList", BindingFlags.Public | BindingFlags.Instance); + actualKnownVesselsList = knownVesselsListMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualKnownVesselsList != null).ToString()); + + LogFormatted("Getting KnownFreezerParts Object"); + knownFreezerPartsMethod = DFType.GetMethod("get_KnownFreezerParts", BindingFlags.Public | BindingFlags.Instance); + actualKnownFreezerParts = knownFreezerPartsMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualKnownFreezerParts != null).ToString()); + + LogFormatted("Getting KnownFreezerParts Object"); + knownFreezerPartsListMethod = DFType.GetMethod("get_KnownFreezerPartsList", BindingFlags.Public | BindingFlags.Instance); + actualKnownFreezerPartsList = knownFreezerPartsListMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualKnownFreezerPartsList != null).ToString()); + + LogFormatted("Getting EcRequired Object"); + ActualECReqdMethod = DFType.GetMethod("get_DFIECReqd"); + actualECReqdField = ActualECReqdMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (actualECReqdField != null).ToString()); + + LogFormatted("Getting DeathFatal Object"); + ActualDeathFatalMethod = DFType.GetMethod("get_DFIDeathFatal"); + ActualDeathFatalField = ActualDeathFatalMethod.Invoke(actualDFAPI, null); + LogFormatted("Success: " + (ActualDeathFatalField != 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); + } + } + + private object actualECReqdField; + private MethodInfo ActualECReqdMethod; + /// + /// Is EC required to run the DeepFreeze Freezers (Deepfreeze difficulty setting) + /// + public bool ECReqd + { + get + { + if (actualECReqdField == null) + return false; + + return (Boolean)actualECReqdField; + } + } + + private object ActualDeathFatalField; + private MethodInfo ActualDeathFatalMethod; + /// + /// Is Death fatal or do kerals respawn? (Deepfreeze difficulty setting) + /// + public bool DeathFatal + { + get + { + if (ActualDeathFatalField == null) + return false; + + return (Boolean)ActualDeathFatalField; + } + } + + private MethodInfo ActualKillFrozenCrewMethod; + + public void KillFrozenCrew(string crewMember) + { + ActualKillFrozenCrewMethod.Invoke(actualDFAPI, new object[] { crewMember }); + } + + #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 + { + Dictionary returnvalue = new Dictionary(); + if (FrozenKerbalsMethod == null) + { + LogFormatted("Error getting FrozenKerbals - Reflection Method is Null"); + return returnvalue; + } + //object actualDFtest = DFType.GetField("Instance", BindingFlags.Public | BindingFlags.Static).GetValue(null); + //FieldInfo gamesettingsfield = DFType.GetField("DFgameSettings", BindingFlags.Instance | BindingFlags.NonPublic); + //object gamesettings; + //if (gamesettingsfield != null) + // gamesettings = gamesettingsfield.GetValue(actualDFAPI); + actualFrozenKerbals = null; + actualFrozenKerbals = FrozenKerbalsMethod.Invoke(actualDFAPI, null); + 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; + } + + private object actualFrozenKerbalsList; + private MethodInfo FrozenKerbalsListMethod; + + /// + /// This converts the actualFrozenKerbals actual object to a new List keyvaluepair for consumption + /// + /// /// + /// List> of Frozen Kerbals + /// + internal List> FrozenKerbalsList + { + get + { + List> returnvalue = new List>(); + if (FrozenKerbalsListMethod == null) + { + LogFormatted("Error getting FrozenKerbals - Reflection Method is Null"); + return returnvalue; + } + actualFrozenKerbalsList = null; + actualFrozenKerbalsList = FrozenKerbalsListMethod.Invoke(actualDFAPI, null); + returnvalue = (List>)actualFrozenKerbalsList; + return returnvalue; + } + } + + #endregion Frozenkerbals + + #region KnownVessels + + private object actualKnownVessels; + private MethodInfo knownVesselsMethod; + + /// + /// The dictionary of Known Vessels that are currently active in game + /// + /// + /// Dictionary of Known Vessels + /// + internal Dictionary KnownVessels + { + get + { + Dictionary returnvalue = new Dictionary(); + if (knownVesselsMethod == null) + { + LogFormatted("Error getting KnownVessels - Reflection Method is Null"); + return returnvalue; + } + actualKnownVessels = null; + actualKnownVessels = knownVesselsMethod.Invoke(actualDFAPI, null); + returnvalue = ExtractKnownVesselsDict(actualKnownVessels); + return returnvalue; + } + } + + /// + /// This converts the actualKnownVessels actual object to a new dictionary for consumption + /// + /// + /// + /// Dictionary of Known Vessels + /// + private Dictionary ExtractKnownVesselsDict(Object actualKnownVessels) + { + Dictionary DictToReturn = new Dictionary(); + try + { + foreach (var item in (IDictionary)actualKnownVessels) + { + var typeitem = item.GetType(); + PropertyInfo[] itemprops = typeitem.GetProperties(BindingFlags.Instance | BindingFlags.Public); + Guid itemkey = (Guid)itemprops[0].GetValue(item, null); + object itemvalue = (object)itemprops[1].GetValue(item, null); + VesselInfo itemVesselInfo = new VesselInfo(itemvalue); + DictToReturn[itemkey] = itemVesselInfo; + } + } + catch (Exception ex) + { + LogFormatted("Unable to extract KnownVessels Dictionary: {0}", ex.Message); + } + return DictToReturn; + } + + private object actualKnownVesselsList; + private MethodInfo knownVesselsListMethod; + + /// + /// This converts the actualKnownVessels actual object to a new List keyvaluepair for consumption + /// + /// /// + /// List> of Known Vessels + /// + internal List> KnownVesselsList + { + get + { + List> returnvalue = new List>(); + if (knownVesselsListMethod == null) + { + LogFormatted("Error getting KnownVessels - Reflection Method is Null"); + return returnvalue; + } + actualKnownVesselsList = null; + actualKnownVesselsList = knownVesselsListMethod.Invoke(actualDFAPI, null); + returnvalue = (List>)actualKnownVesselsList; + return returnvalue; + } + } + + #endregion KnownVessels + + #region KnownFreezerParts + + private object actualKnownFreezerParts; + private MethodInfo knownFreezerPartsMethod; + + /// + /// The dictionary of Known Parts that are currently active in game + /// + /// + /// Dictionary of Known Freezer Parts + /// + internal Dictionary KnownFreezerParts + { + get + { + Dictionary returnvalue = new Dictionary(); + if (knownFreezerPartsMethod == null) + { + LogFormatted("Error getting KnownFreezerParts - Reflection Method is Null"); + return returnvalue; + } + actualKnownFreezerParts = null; + actualKnownFreezerParts = knownFreezerPartsMethod.Invoke(actualDFAPI, null); + returnvalue = ExtractKnownFreezerPartsDict(actualKnownFreezerParts); + return returnvalue; + } + } + + /// + /// This converts the actualKnownFreezerParts actual object to a new dictionary for consumption + /// + /// + /// + /// Dictionary of Known Vessels + /// + private Dictionary ExtractKnownFreezerPartsDict(Object actualKnownFreezerParts) + { + Dictionary DictToReturn = new Dictionary(); + try + { + foreach (var item in (IDictionary)actualKnownFreezerParts) + { + var typeitem = item.GetType(); + PropertyInfo[] itemprops = typeitem.GetProperties(BindingFlags.Instance | BindingFlags.Public); + uint itemkey = (uint)itemprops[0].GetValue(item, null); + object itemvalue = (object)itemprops[1].GetValue(item, null); + PartInfo itemPartInfo = new PartInfo(itemvalue); + DictToReturn[itemkey] = itemPartInfo; + } + } + catch (Exception ex) + { + LogFormatted("Unable to extract KnownFreezerParts Dictionary: {0}", ex.Message); + } + return DictToReturn; + } + + private object actualKnownFreezerPartsList; + private MethodInfo knownFreezerPartsListMethod; + + /// + /// This converts the actualKnownFreezerParts actual object to a new List keyvaluepair for consumption + /// + /// /// + /// List> of Known Freezer Parts + /// + internal List> KnownFreezerPartsList + { + get + { + List> returnvalue = new List>(); + if (knownFreezerPartsListMethod == null) + { + LogFormatted("Error getting KnownFreezerParts - Reflection Method is Null"); + return returnvalue; + } + actualKnownFreezerPartsList = null; + actualKnownFreezerPartsList = knownFreezerPartsListMethod.Invoke(actualDFAPI, null); + returnvalue = (List>)actualKnownFreezerPartsList; + return returnvalue; + } + } + + #endregion KnownFreezerParts + } + + #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; + FrznChargeUsageMethod = DeepFreezerType.GetMethod("get_DFIFrznChargeUsage", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FrznChargeUsage = getFrznChargeUsage; + StoredCrewListMethod = DeepFreezerType.GetMethod("get_DFIStoredCrewList", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + actualStoredCrewList = StoredCrewListMethod.Invoke(actualDeepFreezer, null); + ECReqdMethod = DeepFreezerType.GetMethod("get_DFIECReqd", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + ECReqd = getECReqd; + FrznChargeRequiredMethod = DeepFreezerType.GetMethod("get_DFIFrznChargeRequired", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FrznChargeRequired = getFrznChargeRequired; + + //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); } + } + + /// + /// True if this DeepFreezer requires Electric Charge for frozen Kerbals + /// + public bool ECReqd; + + private MethodInfo ECReqdMethod; + + private bool getECReqd + { + get { return (bool)ECReqdMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The current EC Usage of this DeepFreezer + /// + public float FrznChargeUsage; + + private MethodInfo FrznChargeUsageMethod; + + private float getFrznChargeUsage + { + get { return (float)FrznChargeUsageMethod.Invoke(actualDeepFreezer, null); } + } + + /// + /// The EC Usage of this DeepFreezer Per Kerbal per minute + /// + public int FrznChargeRequired; + + private MethodInfo FrznChargeRequiredMethod; + + private int getFrznChargeRequired + { + get { return (int)FrznChargeRequiredMethod.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); } + } + } + + /// + /// The Value Class of the KnownVesselsList Dictionary that is an analogue of the real KnownVessels Dictionary in the DeepFreezer Class. + /// + public class VesselInfo + { + internal VesselInfo(Object a) + { + actualVesselInfo = a; + vesselNameField = VesselInfoType.GetField("vesselName"); + vesselTypeField = VesselInfoType.GetField("vesselType"); + numCrewField = VesselInfoType.GetField("numCrew"); + numSeatsField = VesselInfoType.GetField("numSeats"); + numOccupiedPartsField = VesselInfoType.GetField("numOccupiedParts"); + numFrozenCrewField = VesselInfoType.GetField("numFrznCrew"); + hibernatingField = VesselInfoType.GetField("hibernating"); + hasExternalDoorField = VesselInfoType.GetField("hasextDoor"); + hasExternalPodField = VesselInfoType.GetField("hasextPod"); + lastUpdateField = VesselInfoType.GetField("lastUpdate"); + storedECField = VesselInfoType.GetField("storedEC"); + predictedECOutField = VesselInfoType.GetField("predictedECOut"); + } + + private Object actualVesselInfo; + + private FieldInfo vesselNameField; + + /// + /// The Vessel Name + /// + public string vesselName + { + get { return (string)vesselNameField.GetValue(actualVesselInfo); } + } + private FieldInfo vesselTypeField; + + /// + /// last time the FrozenKerbalInfo was updated + /// + public VesselType vesselType + { + get { return (VesselType)vesselTypeField.GetValue(actualVesselInfo); } + } + + private FieldInfo numCrewField; + + /// + /// Number of Crew + /// + public int numCrew + { + get { return (int)numCrewField.GetValue(actualVesselInfo); } + } + + private FieldInfo numSeatsField; + + /// + /// Number of Seats + /// + public int numSeats + { + get { return (int)numSeatsField.GetValue(actualVesselInfo); } + } + + private FieldInfo numOccupiedPartsField; + + /// + /// Number of Occupied parts + /// + public int numOccupiedParts + { + get { return (int)numOccupiedPartsField.GetValue(actualVesselInfo); } + } + + private FieldInfo numFrozenCrewField; + + /// + /// Number of Frozen Crew + /// + public int numFrozenCrew + { + get { return (int)numFrozenCrewField.GetValue(actualVesselInfo); } + } + + private FieldInfo hibernatingField; + + /// + /// Is the vessel hibernating + /// + public bool hibernating + { + get { return (bool)hibernatingField.GetValue(actualVesselInfo); } + } + + private FieldInfo hasExternalDoorField; + + /// + /// If there's an external door + /// + public bool hasExternalDoor + { + get { return (bool)hasExternalDoorField.GetValue(actualVesselInfo); } + } + + private FieldInfo hasExternalPodField; + + /// + /// If there's an external pod + /// + public bool hasExternalPod + { + get { return (bool)hasExternalPodField.GetValue(actualVesselInfo); } + } + + private FieldInfo lastUpdateField; + + /// + /// Last time updated + /// + public double lastUpdate + { + get { return (double)lastUpdateField.GetValue(actualVesselInfo); } + } + + private FieldInfo storedECField; + + /// + /// How much EC it has stored + /// + public double storedEC + { + get { return (double)storedECField.GetValue(actualVesselInfo); } + set { storedECField.SetValue(actualVesselInfo, value); } + } + + private FieldInfo predictedECOutField; + + /// + /// Predicted time EC will run out + /// + public double predictedECOut + { + get { return (double)predictedECOutField.GetValue(actualVesselInfo); } + } + } + + + /// + /// The Value Class of the KnownFreezerPartsList Dictionary that is an analogue of the real KnownFreezerParts Dictionary in the DeepFreezer Class. + /// + public class PartInfo + { + internal PartInfo(Object a) + { + actualPartInfo = a; + vesselIDField = PartInfoType.GetField("vesselID"); + partNameField = PartInfoType.GetField("PartName"); + numSeatsField = PartInfoType.GetField("numSeats"); + numCrewField = PartInfoType.GetField("numCrew"); + crewMembersField = PartInfoType.GetField("crewMembers"); + crewMemberTraitsField = PartInfoType.GetField("crewMemberTraits"); + numFrznCrewField = PartInfoType.GetField("numFrznCrew"); + hibernatingField = PartInfoType.GetField("hibernating"); + hasExternalDoorField = PartInfoType.GetField("hasextDoor"); + hasExternalPodField = PartInfoType.GetField("hasextPod"); + timeLastElectricityField = PartInfoType.GetField("timeLastElectricity"); + frznChargeRequiredField = PartInfoType.GetField("frznChargeRequired"); + timeLastTempCheckField = PartInfoType.GetField("timeLastTempCheck"); + deathCounterField = PartInfoType.GetField("deathCounter"); + tmpdeathCounterField = PartInfoType.GetField("tmpdeathCounter"); + outofECField = PartInfoType.GetField("outofEC"); + TmpStatusField = PartInfoType.GetField("TmpStatus"); + ECWarningField = PartInfoType.GetField("ECWarning"); + TempWarningField = PartInfoType.GetField("TempWarning"); + cabinTempField = PartInfoType.GetField("cabinTemp"); + lastUpdateField = PartInfoType.GetField("lastUpdate"); + } + + private Object actualPartInfo; + + private FieldInfo vesselIDField; + + /// + /// Guid of the vessel of the Part + /// + public Guid vesselID + { + get { return (Guid)vesselIDField.GetValue(actualPartInfo); } + } + + private FieldInfo partNameField; + + /// + /// The Part Name + /// + public string partName + { + get { return (string)partNameField.GetValue(actualPartInfo); } + } + + private FieldInfo numSeatsField; + + /// + /// Number of Seats + /// + public int numSeats + { + get { return (int)numSeatsField.GetValue(actualPartInfo); } + } + + private FieldInfo numCrewField; + + /// + /// Number of Crew + /// + public int numCrew + { + get { return (int)numCrewField.GetValue(actualPartInfo); } + set { numCrewField.SetValue(actualPartInfo, value); } + } + + private FieldInfo crewMembersField; + + /// + /// List of Crew Members names + /// + public List crewMembers + { + get { return (List)crewMembersField.GetValue(actualPartInfo); } + set { crewMembersField.SetValue(actualPartInfo, value); } + } + + private FieldInfo crewMemberTraitsField; + + /// + /// List of Crew Members traits + /// + public List crewMemberTraits + { + get { return (List)crewMemberTraitsField.GetValue(actualPartInfo); } + set { crewMemberTraitsField.SetValue(actualPartInfo, value); } + } + + private FieldInfo numFrznCrewField; + + /// + /// Number of Frozen Crew + /// + public int numFrznCrew + { + get { return (int)numFrznCrewField.GetValue(actualPartInfo); } + set { numFrznCrewField.SetValue(actualPartInfo, value); } + } + + private FieldInfo hibernatingField; + + /// + /// Is the vessel hibernating + /// + public bool hibernating + { + get { return (bool)hibernatingField.GetValue(actualPartInfo); } + } + + private FieldInfo hasExternalDoorField; + + /// + /// If there's an external door + /// + public bool hasExternalDoor + { + get { return (bool)hasExternalDoorField.GetValue(actualPartInfo); } + } + + private FieldInfo hasExternalPodField; + + /// + /// If there's an external pod + /// + public bool hasExternalPod + { + get { return (bool)hasExternalPodField.GetValue(actualPartInfo); } + } + + private FieldInfo timeLastElectricityField; + /// + /// Time last EC was taken + /// + public double timeLastElectricity + { + get { return (double)timeLastElectricityField.GetValue(actualPartInfo); } + set { timeLastElectricityField.SetValue(actualPartInfo, value); } + } + + private FieldInfo frznChargeRequiredField; + /// + /// The amount of EC required to keep a kerbal frozen. + /// + public double frznChargeRequired + { + get { return (double)frznChargeRequiredField.GetValue(actualPartInfo); } + set { frznChargeRequiredField.SetValue(actualPartInfo, value); } + } + + private FieldInfo timeLastTempCheckField; + /// + /// The time the temperature was last checked. + /// + public double timeLastTempCheck + { + get { return (double)timeLastTempCheckField.GetValue(actualPartInfo); } + set { timeLastTempCheckField.SetValue(actualPartInfo, value); } + } + + private FieldInfo deathCounterField; + /// + /// The time counter until death occurs after EC runs out. + /// + public double deathCounter + { + get { return (double)deathCounterField.GetValue(actualPartInfo); } + set { deathCounterField.SetValue(actualPartInfo, value); } + } + + private FieldInfo tmpdeathCounterField; + /// + /// The amount of EC required to keep a kerbal frozen. + /// + public double tmpdeathCounter + { + get { return (double)tmpdeathCounterField.GetValue(actualPartInfo); } + set { tmpdeathCounterField.SetValue(actualPartInfo, value); } + } + + private FieldInfo outofECField; + /// + /// If the part freezer is out of EC or not. + /// + public bool outofEC + { + get { return (bool)outofECField.GetValue(actualPartInfo); } + set { outofECField.SetValue(actualPartInfo, value); } + } + + private FieldInfo TmpStatusField; + /// + /// The freezer temperature status. + /// + public FrzrTmpStatus TmpStatus + { + get { return (FrzrTmpStatus)TmpStatusField.GetValue(actualPartInfo); } + set { TmpStatusField.SetValue(actualPartInfo, value); } + } + + private FieldInfo ECWarningField; + /// + /// If the part freezer is out of EC or not. + /// + public bool ECWarning + { + get { return (bool)ECWarningField.GetValue(actualPartInfo); } + set { ECWarningField.SetValue(actualPartInfo, value); } + } + + private FieldInfo TempWarningField; + /// + /// If a temperature warning is in effect. + /// + public bool TempWarning + { + get { return (bool)TempWarningField.GetValue(actualPartInfo); } + set { TempWarningField.SetValue(actualPartInfo, value); } + } + + private FieldInfo cabinTempField; + /// + /// The cabin temperature. + /// + public float cabinTempRequired + { + get { return (float)cabinTempField.GetValue(actualPartInfo); } + set { cabinTempField.SetValue(actualPartInfo, value); } + } + + private FieldInfo lastUpdateField; + + /// + /// Last time updated + /// + public double lastUpdate + { + get { return (double)lastUpdateField.GetValue(actualPartInfo); } + set { lastUpdateField.SetValue(actualPartInfo, value); } + } + } + + + #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/APIs/KACWrapper.cs b/Source/APIs/KACWrapper.cs new file mode 100644 index 0000000..4bc7296 --- /dev/null +++ b/Source/APIs/KACWrapper.cs @@ -0,0 +1,665 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Debug = UnityEngine.Debug; + +// TODO: Change this namespace to something specific to your plugin here. +//EG: +// namespace MyPlugin_KACWrapper +namespace DF +{ + /////////////////////////////////////////////////////////////////////////////////////////// + // BELOW HERE SHOULD NOT BE EDITED - this links to the loaded KAC module without requiring a Hard Dependancy + /////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// The Wrapper class to access KAC from another plugin + /// + public class KACWrapper + { + protected static Type KACType; + protected static Type KACAlarmType; + + protected static Object actualKAC; + + /// + /// This is the Kerbal Alarm Clock object + /// + /// SET AFTER INIT + /// + public static KACAPI KAC; + + /// + /// Whether we found the KerbalAlarmClock assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return KACType != null; } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return KAC != null; } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _KACWrapped; + + /// + /// Whether the object has been wrapped and the APIReady flag is set in the real KAC + /// + public static Boolean APIReady { get { return _KACWrapped && KAC.APIReady && !NeedUpgrade; } } + + public static Boolean NeedUpgrade { get; private set; } + + /// + /// This method will set up the KAC object and wrap all the methods/functions + /// + /// + public static Boolean InitKACWrapper() + { + //if (!_KACWrapped ) + //{ + //reset the internal objects + _KACWrapped = false; + actualKAC = null; + KAC = null; + LogFormatted_DebugOnly("Attempting to Grab KAC Types..."); + + //find the base type + KACType = getType("KerbalAlarmClock.KerbalAlarmClock"); + + if (KACType == null) + { + return false; + } + + LogFormatted("KAC Version:{0}", KACType.Assembly.GetName().Version.ToString()); + if (KACType.Assembly.GetName().Version.CompareTo(new Version(3, 0, 0, 5)) < 0) + { + //No TimeEntry or alarmchoice options = need a newer version + NeedUpgrade = true; + } + + //now the Alarm Type + KACAlarmType = getType("KerbalAlarmClock.KACAlarm"); + + if (KACAlarmType == null) + { + return false; + } + + //now grab the running instance + LogFormatted_DebugOnly("Got Assembly Types, grabbing Instance"); + + try + { + actualKAC = KACType.GetField("APIInstance", BindingFlags.Public | BindingFlags.Static).GetValue(null); + } + catch (Exception) + { + NeedUpgrade = true; + LogFormatted("No APIInstance found - most likely you have KAC v2 installed"); + //throw; + } + if (actualKAC == null) + { + LogFormatted("Failed grabbing Instance"); + return false; + } + + //If we get this far we can set up the local object and its methods/functions + LogFormatted_DebugOnly("Got Instance, Creating Wrapper Objects"); + KAC = new KACAPI(actualKAC); + //} + _KACWrapped = true; + return true; + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + /// + /// The Type that is an analogue of the real KAC. This lets you access all the API-able properties and Methods of the KAC + /// + public class KACAPI + { + internal KACAPI(Object KAC) + { + //store the actual object + actualKAC = KAC; + + //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 + LogFormatted_DebugOnly("Getting APIReady Object"); + APIReadyField = KACType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); + LogFormatted_DebugOnly("Success: " + (APIReadyField != null)); + + //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPEL HERE + LogFormatted_DebugOnly("Getting Alarms Object"); + AlarmsField = KACType.GetField("alarms", BindingFlags.Public | BindingFlags.Static); + actualAlarms = AlarmsField.GetValue(actualKAC); + LogFormatted_DebugOnly("Success: " + (actualAlarms != null)); + + //Events + LogFormatted_DebugOnly("Getting Alarm State Change Event"); + onAlarmStateChangedEvent = KACType.GetEvent("onAlarmStateChanged", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (onAlarmStateChangedEvent != null)); + LogFormatted_DebugOnly("Adding Handler"); + AddHandler(onAlarmStateChangedEvent, actualKAC, AlarmStateChanged); + + //Methods + LogFormatted_DebugOnly("Getting Create Method"); + CreateAlarmMethod = KACType.GetMethod("CreateAlarm", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (CreateAlarmMethod != null)); + + LogFormatted_DebugOnly("Getting Delete Method"); + DeleteAlarmMethod = KACType.GetMethod("DeleteAlarm", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (DeleteAlarmMethod != null)); + + LogFormatted_DebugOnly("Getting DrawAlarmAction"); + DrawAlarmActionChoiceMethod = KACType.GetMethod("DrawAlarmActionChoiceAPI", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (DrawAlarmActionChoiceMethod != null)); + + //LogFormatted("Getting DrawTimeEntry"); + //DrawTimeEntryMethod = KACType.GetMethod("DrawTimeEntryAPI", BindingFlags.Public | BindingFlags.Instance); + //LogFormatted_DebugOnly("Success: " + (DrawTimeEntryMethod != null).ToString()); + + //Commenting out rubbish lines + //MethodInfo[] mis = KACType.GetMethods(BindingFlags.Public | BindingFlags.Instance); + //foreach (MethodInfo mi in mis) + //{ + // LogFormatted("M:{0}-{1}", mi.Name, mi.DeclaringType); + //} + } + + private Object actualKAC; + + private FieldInfo APIReadyField; + + /// + /// Whether the APIReady flag is set in the real KAC + /// + public Boolean APIReady + { + get + { + if (APIReadyField == null) + return false; + + return (Boolean)APIReadyField.GetValue(null); + } + } + + #region Alarms + + private Object actualAlarms; + private FieldInfo AlarmsField; + + /// + /// The list of Alarms that are currently active in game + /// + internal KACAlarmList Alarms + { + get + { + return ExtractAlarmList(actualAlarms); + } + } + + /// + /// This converts the KACAlarmList actual object to a new List for consumption + /// + /// + /// + private KACAlarmList ExtractAlarmList(Object actualAlarmList) + { + KACAlarmList ListToReturn = new KACAlarmList(); + try + { + //iterate each "value" in the dictionary + + foreach (var item in (IList)actualAlarmList) + { + KACAlarm r1 = new KACAlarm(item); + ListToReturn.Add(r1); + } + } + catch (Exception ex) + { + LogFormatted("ExtractAlarmList failed: {0}", ex.Message); + //throw ex; + // + } + return ListToReturn; + } + + #endregion Alarms + + #region Events + + /// + /// Takes an EventInfo and binds a method to the event firing + /// + /// EventInfo of the event we want to attach to + /// actual object the eventinfo is gathered from + /// Method that we are going to hook to the event + protected void AddHandler(EventInfo Event, Object KACObject, Action Handler) + { + //build a delegate + Delegate d = Delegate.CreateDelegate(Event.EventHandlerType, Handler.Target, Handler.Method); + //get the Events Add method + MethodInfo addHandler = Event.GetAddMethod(); + //and add the delegate + addHandler.Invoke(KACObject, new Object[] { d }); + } + + //the info about the event; + private EventInfo onAlarmStateChangedEvent; + + /// + /// Event that fires when the State of an Alarm changes + /// + public event AlarmStateChangedHandler onAlarmStateChanged; + + /// + /// Structure of the event delegeate + /// + /// + public delegate void AlarmStateChangedHandler(AlarmStateChangedEventArgs e); + + /// + /// This is the structure that holds the event arguments + /// + public class AlarmStateChangedEventArgs + { + public AlarmStateChangedEventArgs(Object actualEvent, KACAPI kac) + { + Type type = actualEvent.GetType(); + alarm = new KACAlarm(type.GetField("alarm").GetValue(actualEvent)); + eventType = (KACAlarm.AlarmStateEventsEnum)type.GetField("eventType").GetValue(actualEvent); + } + + /// + /// Alarm that has had the state change + /// + public KACAlarm alarm; + + /// + /// What the state was before the event + /// + public KACAlarm.AlarmStateEventsEnum eventType; + } + + /// + /// private function that grabs the actual event and fires our wrapped one + /// + /// actual event from the KAC + private void AlarmStateChanged(object actualEvent) + { + if (onAlarmStateChanged != null) + { + onAlarmStateChanged(new AlarmStateChangedEventArgs(actualEvent, this)); + } + } + + #endregion Events + + #region Methods + + private MethodInfo CreateAlarmMethod; + + /// + /// Create a new Alarm + /// + /// What type of alarm are we creating + /// Name of the Alarm for the display + /// Universal Time for the alarm + /// ID of the newly created alarm + internal String CreateAlarm(AlarmTypeEnum AlarmType, String Name, Double UT) + { + return (String)CreateAlarmMethod.Invoke(actualKAC, new Object[] { (Int32)AlarmType, Name, UT }); + } + + private MethodInfo DeleteAlarmMethod; + + /// + /// Delete an Alarm + /// + /// Unique ID of the alarm + /// Success of the deletion + internal Boolean DeleteAlarm(String AlarmID) + { + return (Boolean)DeleteAlarmMethod.Invoke(actualKAC, new Object[] { AlarmID }); + } + + private MethodInfo DrawAlarmActionChoiceMethod; + + /// + /// Delete an Alarm + /// + /// Unique ID of the alarm + /// Success of the deletion + internal Boolean DrawAlarmActionChoice(ref AlarmActionEnum Choice, String LabelText, Int32 LabelWidth, Int32 ButtonWidth) + { + Int32 InValue = (Int32)Choice; + Int32 OutValue = (Int32)DrawAlarmActionChoiceMethod.Invoke(actualKAC, new Object[] { InValue, LabelText, LabelWidth, ButtonWidth }); + + Choice = (AlarmActionEnum)OutValue; + return InValue != OutValue; + } + + //Remmed out due to it borking window layout + //private MethodInfo DrawTimeEntryMethod; + ///// + ///// Delete an Alarm + ///// + ///// Unique ID of the alarm + ///// Success of the deletion + + //internal Boolean DrawTimeEntry(ref Double Time, TimeEntryPrecisionEnum Prec, String LabelText, Int32 LabelWidth) + //{ + // Double InValue = Time; + // Double OutValue = (Double)DrawTimeEntryMethod.Invoke(actualKAC, new System.Object[] { InValue, (Int32)Prec, LabelText, LabelWidth }); + + // Time = OutValue; + // return (InValue != OutValue); + //} + + #endregion Methods + + public class KACAlarm + { + internal KACAlarm(Object a) + { + actualAlarm = a; + VesselIDField = KACAlarmType.GetField("VesselID"); + IDField = KACAlarmType.GetField("ID"); + NameField = KACAlarmType.GetField("Name"); + NotesField = KACAlarmType.GetField("Notes"); + AlarmTypeField = KACAlarmType.GetField("TypeOfAlarm"); + AlarmTimeProperty = KACAlarmType.GetProperty("AlarmTimeUT"); + AlarmMarginField = KACAlarmType.GetField("AlarmMarginSecs"); + AlarmActionField = KACAlarmType.GetField("AlarmAction"); + RemainingField = KACAlarmType.GetField("Remaining"); + + XferOriginBodyNameField = KACAlarmType.GetField("XferOriginBodyName"); + //LogFormatted("XFEROrigin:{0}", XferOriginBodyNameField == null); + XferTargetBodyNameField = KACAlarmType.GetField("XferTargetBodyName"); + + RepeatAlarmField = KACAlarmType.GetField("RepeatAlarm"); + RepeatAlarmPeriodProperty = KACAlarmType.GetProperty("RepeatAlarmPeriodUT"); + + //PropertyInfo[] pis = KACAlarmType.GetProperties(); + //foreach (PropertyInfo pi in pis) + //{ + // LogFormatted("P:{0}-{1}", pi.Name, pi.DeclaringType); + //} + //FieldInfo[] fis = KACAlarmType.GetFields(); + //foreach (FieldInfo fi in fis) + //{ + // LogFormatted("F:{0}-{1}", fi.Name, fi.DeclaringType); + //} + } + + private Object actualAlarm; + + private FieldInfo VesselIDField; + + /// + /// Unique Identifier of the Vessel that the alarm is attached to + /// + public String VesselID + { + get { return (String)VesselIDField.GetValue(actualAlarm); } + set { VesselIDField.SetValue(actualAlarm, value); } + } + + private FieldInfo IDField; + + /// + /// Unique Identifier of this alarm + /// + public String ID + { + get { return (String)IDField.GetValue(actualAlarm); } + } + + private FieldInfo NameField; + + /// + /// Short Text Name for the Alarm + /// + public String Name + { + get { return (String)NameField.GetValue(actualAlarm); } + set { NameField.SetValue(actualAlarm, value); } + } + + private FieldInfo NotesField; + + /// + /// Longer Text Description for the Alarm + /// + public String Notes + { + get { return (String)NotesField.GetValue(actualAlarm); } + set { NotesField.SetValue(actualAlarm, value); } + } + + private FieldInfo XferOriginBodyNameField; + + /// + /// Name of the origin body for a transfer + /// + public String XferOriginBodyName + { + get { return (String)XferOriginBodyNameField.GetValue(actualAlarm); } + set { XferOriginBodyNameField.SetValue(actualAlarm, value); } + } + + private FieldInfo XferTargetBodyNameField; + + /// + /// Name of the destination body for a transfer + /// + public String XferTargetBodyName + { + get { return (String)XferTargetBodyNameField.GetValue(actualAlarm); } + set { XferTargetBodyNameField.SetValue(actualAlarm, value); } + } + + private FieldInfo AlarmTypeField; + + /// + /// What type of Alarm is this - affects icon displayed and some calc options + /// + public AlarmTypeEnum AlarmType { get { return (AlarmTypeEnum)AlarmTypeField.GetValue(actualAlarm); } } + + private PropertyInfo AlarmTimeProperty; + + /// + /// In game UT value of the alarm + /// + public Double AlarmTime + { + get { return (Double)AlarmTimeProperty.GetValue(actualAlarm, null); } + set { AlarmTimeProperty.SetValue(actualAlarm, value, null); } + } + + private FieldInfo AlarmMarginField; + + /// + /// In game seconds the alarm will fire before the event it is for + /// + public Double AlarmMargin + { + get { return (Double)AlarmMarginField.GetValue(actualAlarm); } + set { AlarmMarginField.SetValue(actualAlarm, value); } + } + + private FieldInfo AlarmActionField; + + /// + /// What should the Alarm Clock do when the alarm fires + /// + public AlarmActionEnum AlarmAction + { + get { return (AlarmActionEnum)AlarmActionField.GetValue(actualAlarm); } + set { AlarmActionField.SetValue(actualAlarm, (Int32)value); } + } + + private FieldInfo RemainingField; + + /// + /// How much Game time is left before the alarm fires + /// + public Double Remaining { get { return (Double)RemainingField.GetValue(actualAlarm); } } + + private FieldInfo RepeatAlarmField; + + /// + /// Whether the alarm will be repeated after it fires + /// + public Boolean RepeatAlarm + { + get { return (Boolean)RepeatAlarmField.GetValue(actualAlarm); } + set { RepeatAlarmField.SetValue(actualAlarm, value); } + } + + private PropertyInfo RepeatAlarmPeriodProperty; + + /// + /// Value in Seconds after which the alarm will repeat + /// + public Double RepeatAlarmPeriod + { + get + { + try { return (Double)RepeatAlarmPeriodProperty.GetValue(actualAlarm, null); } + catch (Exception) { return 0; } + } + set { RepeatAlarmPeriodProperty.SetValue(actualAlarm, value, null); } + } + + public enum AlarmStateEventsEnum + { + Created, + Triggered, + Closed, + Deleted + } + } + + public enum AlarmTypeEnum + { + Raw, + Maneuver, + ManeuverAuto, + Apoapsis, + Periapsis, + AscendingNode, + DescendingNode, + LaunchRendevous, + Closest, + SOIChange, + SOIChangeAuto, + Transfer, + TransferModelled, + Distance, + Crew, + EarthTime, + Contract, + ContractAuto + } + + public enum AlarmActionEnum + { + [Description("Do Nothing-Delete When Past")] + DoNothingDeleteWhenPassed, + + [Description("Do Nothing")] + DoNothing, + + [Description("Message Only-No Affect on warp")] + MessageOnly, + + [Description("Kill Warp Only-No Message")] + KillWarpOnly, + + [Description("Kill Warp and Message")] + KillWarp, + + [Description("Pause Game and Message")] + PauseGame + } + + public enum TimeEntryPrecisionEnum + { + Seconds = 0, + Minutes = 1, + Hours = 2, + Days = 3, + Years = 4 + } + + public class KACAlarmList : List + { + } + } + + #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 + + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + if (RSTUtils.Utilities.debuggingOn) + 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, Assembly.GetExecutingAssembly().GetName().Name, + MethodBase.GetCurrentMethod().DeclaringType.Name); + Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/APIs/KBWrapper.cs b/Source/APIs/KBWrapper.cs new file mode 100644 index 0000000..b4c71b6 --- /dev/null +++ b/Source/APIs/KBWrapper.cs @@ -0,0 +1,189 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton based of code and concepts from the Kerbal Alarm Clock Mod. Which was licensed under the MIT license. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Debug = UnityEngine.Debug; + +namespace DF +{ + /// + /// The Wrapper class to access KB LS + /// + public class KBWrapper + { + protected static Type KBType; + protected static Object actualKB; + + /// + /// This is the KB LS Actual object + /// + /// SET AFTER INIT + /// + public static KBAPI KBActualAPI; + + /// + /// Whether we found the KB LS assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return KBType != null; } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return KBActualAPI != null; } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _KBWrapped; + + /// + /// Whether the object has been wrapped + /// + public static Boolean APIReady { get { return _KBWrapped; } } + + /// + /// This method will set up the KB LS object and wrap all the methods/functions + /// + /// + public static Boolean InitKBWrapper() + { + //reset the internal objects + _KBWrapped = false; + actualKB = null; + LogFormatted_DebugOnly("Attempting to Grab KB LS Types..."); + + //find the base type + KBType = getType("KERBALISM.API"); + + if (KBType == null) + { + return false; + } + + LogFormatted("KB LS Version:{0}", KBType.Assembly.GetName().Version.ToString()); + + //If we get this far we can set up the local object and its methods/functions + LogFormatted_DebugOnly("Got Instance, Creating Wrapper Objects"); + KBActualAPI = new KBAPI(); + //KBIsKerbalTracked = new KBIsKerbalTrackedAPI(actualKBIsKerbalTracked); + + _KBWrapped = true; + return true; + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + /// + /// The Type that is an analogue of the real KB LS. This lets you access all the API-able properties and Methods of KB LS + public class KBAPI + { + internal KBAPI() + { + //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 + //LogFormatted("Getting APIReady Object"); + //APIReadyField = TRType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); + //LogFormatted("Success: " + (APIReadyField != null).ToString()); + + //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPLE HERE + //Methods + LogFormatted_DebugOnly("Getting hook_DisableKerbal Method"); + KBhook_DisableKerbalMethod = KBType.GetMethod("DisableKerbal", BindingFlags.Public | BindingFlags.Static); + LogFormatted_DebugOnly("Success: " + (KBhook_DisableKerbalMethod != null)); + } + + #region Methods + + private MethodInfo KBhook_DisableKerbalMethod; + + /// + /// Un/track a kerbal in KB LS + /// + /// A string containing the kerbal's name + /// A bool to disable or enable + internal void DisableKerbal(string kerbal, bool disabled) + { + try + { + KBhook_DisableKerbalMethod.Invoke(null, new System.Object[] { kerbal, disabled }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke KB LS DisableKerbal Method"); + LogFormatted("Exception: {0}", ex); + //throw; + } + } + #endregion Methods + } + + + #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 + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + if (RSTUtils.Utilities.debuggingOn) + 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, Assembly.GetExecutingAssembly().GetName().Name, + MethodBase.GetCurrentMethod().DeclaringType.Name); + Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/APIs/RTWrapper.cs b/Source/APIs/RTWrapper.cs new file mode 100644 index 0000000..94896f4 --- /dev/null +++ b/Source/APIs/RTWrapper.cs @@ -0,0 +1,263 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton based of code and concepts from the Kerbal Alarm Clock Mod. Which was licensed under the MIT license. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Debug = UnityEngine.Debug; + +namespace DF +{ + /// + /// The Wrapper class to access Remote Tech + /// + public class RTWrapper + { + protected static Type RTAPIType; + protected static Object actualRTAPI; + + /// + /// This is the Remote Tech API object + /// + /// SET AFTER INIT + /// + public static RTAPI RTactualAPI; + + /// + /// Whether we found the Remote Tech API assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return RTAPIType != null; } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return actualRTAPI != null; } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _RTWrapped; + + /// + /// Whether the object has been wrapped + /// + public static Boolean APIReady { get { return _RTWrapped; } } + + /// + /// This method will set up the Remote Tech object and wrap all the methods/functions + /// + /// This option will force the Init function to rebind everything + /// + public static Boolean InitTRWrapper() + { + //reset the internal objects + _RTWrapped = false; + actualRTAPI = null; + LogFormatted_DebugOnly("Attempting to Grab Remote Tech Types..."); + + //find the base type + RTAPIType = getType("RemoteTech.API.API"); + + if (RTAPIType == null) + { + return false; + } + + LogFormatted("Remote Tech Version:{0}", RTAPIType.Assembly.GetName().Version.ToString()); + + //now grab the running instance + LogFormatted_DebugOnly("Got Assembly Types, grabbing Instances"); + try + { + actualRTAPI = RTAPIType.GetMember("HasLocalControl", BindingFlags.Public | BindingFlags.Static); + } + catch (Exception) + { + LogFormatted("No Remote Tech isInitialised found"); + //throw; + } + + if (actualRTAPI == null) + { + LogFormatted("Failed grabbing Instance"); + return false; + } + + //If we get this far we can set up the local object and its methods/functions + LogFormatted_DebugOnly("Got Instance, Creating Wrapper Objects"); + RTactualAPI = new RTAPI(actualRTAPI); + + _RTWrapped = true; + return true; + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + /// + /// The Type that is an analogue of the real Remote Tech. This lets you access all the API-able properties and Methods of Remote Tech + /// + public class RTAPI + { + internal RTAPI(Object actualRT) + { + //store the actual object + APIactualRT = actualRT; + + //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 + + //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPLE HERE + //Methods + LogFormatted_DebugOnly("Getting HasLocalControl Method"); + HasLocalControlMethod = RTAPIType.GetMethod("HasLocalControl", BindingFlags.Public | BindingFlags.Static); + LogFormatted_DebugOnly("Success: " + (HasLocalControlMethod != null)); + + LogFormatted_DebugOnly("Getting HasAnyConnection Method"); + HasAnyConnectionMethod = RTAPIType.GetMethod("HasAnyConnection", BindingFlags.Public | BindingFlags.Static); + LogFormatted_DebugOnly("Success: " + (HasAnyConnectionMethod != null)); + + LogFormatted_DebugOnly("Getting GetShortestSignalDelay Method"); + GetShortestSignalDelayMethod = RTAPIType.GetMethod("GetShortestSignalDelay", BindingFlags.Public | BindingFlags.Static); + LogFormatted_DebugOnly("Success: " + (GetShortestSignalDelayMethod != null)); + } + + private Object APIactualRT; + + #region Methods + + private MethodInfo HasLocalControlMethod; + + /// + /// Whether the current vessel HasLocalControl + /// + /// The vessel id reference + /// Success of call + internal bool HasLocalControl(Guid id) + { + try + { + return (bool)HasLocalControlMethod.Invoke(APIactualRT, new Object[] { id }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke Remote Tech HasLocalControl Method"); + LogFormatted("Exception: {0}", ex); + return false; + //throw; + } + } + + private MethodInfo HasAnyConnectionMethod; + + /// + /// Whether the current vessel HasAnyConnection + /// + /// The vessel id reference + /// Success of call + internal bool HasAnyConnection(Guid id) + { + try + { + return (bool)HasAnyConnectionMethod.Invoke(APIactualRT, new Object[] { id }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke Remote Tech HasAnyConnection Method"); + LogFormatted("Exception: {0}", ex); + return false; + //throw; + } + } + + private MethodInfo GetShortestSignalDelayMethod; + + /// + /// Gets the signal delay + /// + /// The vessel id reference + /// A double indicating the signaldelay time + internal double GetShortestSignalDelay(Guid id) + { + try + { + return (double)GetShortestSignalDelayMethod.Invoke(APIactualRT, new Object[] { id }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke Remote Tech GetShortestSignalDelay Method"); + LogFormatted("Exception: {0}", ex); + return 0; + //throw; + } + } + + #endregion Methods + } + + #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 + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + if (RSTUtils.Utilities.debuggingOn) + 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, Assembly.GetExecutingAssembly().GetName().Name, + MethodBase.GetCurrentMethod().DeclaringType.Name); + Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/APIs/SMwrapper.cs b/Source/APIs/SMwrapper.cs new file mode 100644 index 0000000..d2cb0e5 --- /dev/null +++ b/Source/APIs/SMwrapper.cs @@ -0,0 +1,548 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Debug = UnityEngine.Debug; + +namespace DF +{ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // BELOW HERE SHOULD NOT BE EDITED - this links to the loaded ShipManifest module without requiring a Hard Dependancy + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// The Wrapper class to access ShipManifest from another plugin + /// + public class SMWrapper + { + protected static Type SMType; + protected static Type TransferCrewType; + protected static Object actualSM; + + /// + /// This is the ShipManifest object + /// + /// SET AFTER INIT + /// + public static SMAPI ShipManifestAPI; + + /// + /// Whether we found the ShipManifest assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return SMType != null && TransferCrewType != null; } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return ShipManifestAPI != null; } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _SMWrapped; + + /// + /// Whether the object has been wrapped and the APIReady flag is set in the real ShipManifest + /// + public static Boolean SMAPIReady { get { return _SMWrapped; } } + + /// + /// This method will set up the ShipManifest object and wrap all the methods/functions + /// + /// + /// Bool indicating success of call + /// + public static Boolean InitSMWrapper() + { + try + { + //reset the internal objects + _SMWrapped = false; + actualSM = null; + ShipManifestAPI = null; + LogFormatted_DebugOnly("Attempting to Grab ShipManifest Types..."); + + //find the base type + SMType = getType("ShipManifest.SMAddon"); + + if (SMType == null) + { + return false; + } + + LogFormatted("ShipManifest Version:{0}", SMType.Assembly.GetName().Version.ToString()); + + //now the KerbalInfo Type + TransferCrewType = getType("ShipManifest.Process.TransferCrew"); + + if (TransferCrewType == null) + { + return false; + } + + //now grab the running instance + LogFormatted_DebugOnly("Got Assembly Types, grabbing Instance"); + try + { + actualSM = SMType.GetField("Instance", BindingFlags.Public | BindingFlags.Static).GetValue(null); + } + catch (Exception) + { + LogFormatted("No Instance found - most likely you have an old ShipManifest installed"); + return false; + } + if (actualSM == null) + { + LogFormatted("Failed grabbing SMAddon Instance"); + return false; + } + + //If we get this far we can set up the local object and its methods/functions + LogFormatted_DebugOnly("Got Instance, Creating Wrapper Objects"); + ShipManifestAPI = new SMAPI(actualSM); + _SMWrapped = true; + return true; + } + catch (Exception ex) + { + LogFormatted("Unable to setup InitSMrapper Reflection"); + LogFormatted("Exception: {0}", ex); + _SMWrapped = false; + return false; + } + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + /// + /// The API Class that is an analogue of the real ShipManifest. This lets you access all the API-able properties and Methods of the ShipManifest + /// + public class SMAPI + { + internal SMAPI(Object a) + { + try + { + //store the actual object + actualSMAPI = 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 + + LogFormatted_DebugOnly("Getting TransferCrew Instance"); + TransferCrewMethod = SMType.GetMethod("get_CrewTransferProcess", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + actualCrewTransfer = getCrewTransferProcess; + LogFormatted_DebugOnly("Success: " + (TransferCrewMethod != null)); + LogFormatted_DebugOnly("Getting CrewProcessOn Instance"); + CrewProcessOnMethod = SMType.GetMethod("get_CrewProcessOn", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (CrewProcessOnMethod != null)); + LogFormatted_DebugOnly("Getting getCrewXferActiveMethod"); + getCrewXferActiveMethod = TransferCrewType.GetMethod("get_CrewXferActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getCrewXferActiveMethod != null)); + LogFormatted_DebugOnly("Getting setCrewXferActiveMethod"); + setCrewXferActiveMethod = TransferCrewType.GetMethod("set_CrewXferActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (setCrewXferActiveMethod != null)); + LogFormatted_DebugOnly("Getting getIsStockXferMethod"); + getIsStockXferMethod = TransferCrewType.GetMethod("get_IsStockXfer", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getIsStockXferMethod != null)); + LogFormatted_DebugOnly("Getting getOverrideStockCrewXferMethod"); + getOverrideStockCrewXferMethod = TransferCrewType.GetMethod("get_OverrideStockCrewXfer", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getOverrideStockCrewXferMethod != null)); + LogFormatted_DebugOnly("Getting getCrewXferDelaySecMethod"); + getCrewXferDelaySecMethod = TransferCrewType.GetMethod("get_CrewXferDelaySec", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getCrewXferDelaySecMethod != null)); + LogFormatted_DebugOnly("Getting getIsSeat2SeatXferMethod"); + getIsSeat2SeatXferMethod = TransferCrewType.GetMethod("get_IsSeat2SeatXfer", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getIsSeat2SeatXferMethod != null)); + LogFormatted_DebugOnly("Getting getSeat2SeatXferDelaySecMethod"); + getSeat2SeatXferDelaySecMethod = TransferCrewType.GetMethod("get_Seat2SeatXferDelaySec", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getSeat2SeatXferDelaySecMethod != null)); + LogFormatted_DebugOnly("Getting getFromSeatMethod"); + getFromSeatMethod = TransferCrewType.GetMethod("get_FromSeat", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getFromSeatMethod != null)); + LogFormatted_DebugOnly("Getting getToSeatMethod"); + getToSeatMethod = TransferCrewType.GetMethod("get_ToSeat", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getToSeatMethod != null)); + LogFormatted_DebugOnly("Getting getXferVesselIdMethod"); + getXferVesselIdMethod = TransferCrewType.GetMethod("get_XferVesselId", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getXferVesselIdMethod != null)); + LogFormatted_DebugOnly("Getting getIvaDelayActiveMethod"); + getIvaDelayActiveMethod = TransferCrewType.GetMethod("get_IvaDelayActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getIvaDelayActiveMethod != null)); + LogFormatted_DebugOnly("Getting getIvaPortraitDelayMethod"); + getIvaPortraitDelayMethod = TransferCrewType.GetMethod("get_IvaPortraitDelay", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getIvaPortraitDelayMethod != null)); + LogFormatted_DebugOnly("Getting getFromPartMethod"); + getFromPartMethod = TransferCrewType.GetMethod("get_FromPart", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getFromPartMethod != null)); + LogFormatted_DebugOnly("Getting getToPartMethod"); + getToPartMethod = TransferCrewType.GetMethod("get_ToPart", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getToPartMethod != null)); + LogFormatted_DebugOnly("Getting getFromCrewMemberMethod"); + getFromCrewMemberMethod = TransferCrewType.GetMethod("get_FromCrewMember", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getFromCrewMemberMethod != null)); + LogFormatted_DebugOnly("Getting getToCrewMemberMethod"); + getToCrewMemberMethod = TransferCrewType.GetMethod("get_ToCrewMember", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (getToCrewMemberMethod != null)); + } + + catch (Exception ex) + { + LogFormatted("Unable to Instantiate SMAPI object using Reflection"); + LogFormatted("Exception: {0}", ex); + } + } + + private Object actualSMAPI; + private Object actualCrewTransfer; + + /// + /// True if a crewXfer on the Active Vessel is currently active + /// + public bool CrewProcessOn; + + private MethodInfo CrewProcessOnMethod; + private bool getCrewProcessOn + { + get { return (bool)CrewProcessOnMethod.Invoke(actualSMAPI, null); } + } + + private MethodInfo TransferCrewMethod; + /// + /// Get the actual CrewTransfer object from the SMAddon Instance + /// + /// + /// Object reference to the CrewTransfer Instance + /// + public object getCrewTransferProcess + { + get + { + if (TransferCrewMethod == null) + { + return null; + } + + return TransferCrewMethod.Invoke(actualSMAPI, null); + } + } + + private MethodInfo getCrewXferActiveMethod; + private MethodInfo setCrewXferActiveMethod; + /// + /// True if a crewXfter on the Active Vessel is currently active + /// If you set it to False whilst a Xfer is active it will cancel the current transfer + /// + /// + /// Bool + /// + public bool CrewXferActive + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (bool)getCrewXferActiveMethod.Invoke(actualCrewTransfer, null); + } + set + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + setCrewXferActiveMethod.Invoke(actualCrewTransfer, new Object[] { value }); + } + } + + private MethodInfo getIsStockXferMethod; + /// + /// This flag indicates if the transfer was initiated by the Stock Crew Transfer interface. + /// It stays enabled during the Crew Transfer Process (just like CrewXferActive) + /// + /// + /// Bool + /// + public bool IsStockXfer + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (bool)getIsStockXferMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getOverrideStockCrewXferMethod; + /// + /// This flag indicates if SM is overriding the Stock Crew Transfer process. + /// + /// + /// Bool + /// + public bool OverrideStockCrewXfer + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (bool)getOverrideStockCrewXferMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getCrewXferDelaySecMethod; + /// + /// This is the number of seconds delay used for the transfer in progress + /// + /// + /// Double + /// + public double CrewXferDelaySec + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (double)getCrewXferDelaySecMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getIsSeat2SeatXferMethod; + /// + /// This flag indicates if the transfer is Seat 2 seat, i.e. within the same part. + /// + /// + /// Bool + /// + public bool IsSeat2SeatXfer + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (bool)getIsSeat2SeatXferMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getSeat2SeatXferDelaySecMethod; + /// + /// This is the number of seconds used for Seat2seat transfer delays + /// + /// + /// Double + /// + public double Seat2SeatXferDelaySec + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (double)getSeat2SeatXferDelaySecMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getFromSeatMethod; + /// + /// This is the part seat where the kerbal is being moved from. In the case of parts with no internal view, it can be null. + /// + /// + /// InternalSeat + /// + public InternalSeat FromSeat + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (InternalSeat)getFromSeatMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getToSeatMethod; + /// + /// This is the part seat where the kerbal is being moved to. In the case of parts with no internal view, it can be null. + /// + /// + /// internalSeat + /// + public InternalSeat ToSeat + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (InternalSeat)getToSeatMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getXferVesselIdMethod; + /// + /// This is the vessel id for the transfer in question + /// + /// + /// Guid + /// + public Guid XferVesselId + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (Guid)getXferVesselIdMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getIvaDelayActiveMethod; + /// + /// This flag indicates the IVA delay is active. This means that the transfer has occurred (kerbals have actually moved) and we are cleaning up portraits. + /// + /// + /// Bool + /// + public bool IvaDelayActive + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (bool)getIvaDelayActiveMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getIvaPortraitDelayMethod; + /// + /// This stores the number of frames that have passed since transfer has completed. + /// In order for the portraits to update properly, a wait period is needed to allow for unity/ksp async callbacks to complete after crew are moved. + /// This is currently hard coded at 20 Frames (update cycles). I then fire an OnVesselChanged event to refresh the portraits. + /// + /// + /// int + /// + public int IvaPortraitDelay + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (int)getIvaPortraitDelayMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getFromPartMethod; + /// + /// This is the part from which the kerbal is being transferred. + /// + /// + /// Part + /// + public Part FromPart + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (Part)getFromPartMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getToPartMethod; + /// + /// This is the part to which the kerbal is being transferred. It can be the same as the source (Seat2Seat transfers). + /// + /// + /// Part + /// + public Part ToPart + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (Part)getToPartMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getFromCrewMemberMethod; + /// + /// This is the crew member being transferred. + /// + /// + /// ProtoCrewMember + /// + public ProtoCrewMember FromCrewMember + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (ProtoCrewMember)getFromCrewMemberMethod.Invoke(actualCrewTransfer, null); + } + } + + private MethodInfo getToCrewMemberMethod; + /// + /// This is the crew member that would be swapped if the target seat is occupied. can be null. + /// + /// + /// protoCrewMember + /// + public ProtoCrewMember ToCrewMember + { + get + { + if (actualCrewTransfer == null) + actualCrewTransfer = getCrewTransferProcess; + return (ProtoCrewMember)getToCrewMemberMethod.Invoke(actualCrewTransfer, null); + } + } + } + + #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 + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + if (RSTUtils.Utilities.debuggingOn) + 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, Assembly.GetExecutingAssembly().GetName().Name, + MethodBase.GetCurrentMethod().DeclaringType.Name); + Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/APIs/TRWrapper.cs b/Source/APIs/TRWrapper.cs new file mode 100644 index 0000000..cccc4fe --- /dev/null +++ b/Source/APIs/TRWrapper.cs @@ -0,0 +1,233 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton based of code and concepts from the Kerbal Alarm Clock Mod. Which was licensed under the MIT license. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Debug = UnityEngine.Debug; + +namespace DF +{ + /// + /// The Wrapper class to access Texture Replacer + /// + public class TRWrapper + { + protected static Type TRType; + protected static Type TRPersonaliserType; + + protected static Object actualTR; + protected static Object actualTRPersonaliser; + + /// + /// This is the Texture Replacer Personaliser object + /// + /// SET AFTER INIT + /// + public static TRPersonaliserAPI TexRepPersonaliser; + + /// + /// Whether we found the Texture Replacer assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return TRType != null; } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return TexRepPersonaliser != null; } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _TRWrapped; + + /// + /// Whether the object has been wrapped + /// + public static Boolean APIReady { get { return _TRWrapped; } } + + /// + /// This method will set up the Texture Replacer object and wrap all the methods/functions + /// + /// This option will force the Init function to rebind everything + /// + public static Boolean InitTRWrapper() + { + //reset the internal objects + _TRWrapped = false; + actualTR = null; + TexRepPersonaliser = null; + LogFormatted_DebugOnly("Attempting to Grab TextureReplacer Types..."); + + //find the base type + TRType = getType("TextureReplacer.TextureReplacer"); + + if (TRType == null) + { + return false; + } + + LogFormatted("TextureReplacer Version:{0}", TRType.Assembly.GetName().Version.ToString()); + + //find the personaliser class type + TRPersonaliserType = getType("TextureReplacer.Personaliser"); + + if (TRPersonaliserType == null) + { + return false; + } + + //now grab the running instance + LogFormatted_DebugOnly("Got Assembly Types, grabbing Instances"); + try + { + actualTR = TRType.GetField("isInitialised", BindingFlags.Public | BindingFlags.Static).GetValue(null); + } + catch (Exception) + { + LogFormatted("No Texture Replacer isInitialised found"); + //throw; + } + try + { + actualTRPersonaliser = TRPersonaliserType.GetField("instance", BindingFlags.Public | BindingFlags.Static).GetValue(null); + } + catch (Exception) + { + LogFormatted("No Texture Replacer Personaliser Instance found"); + //throw; + } + if (actualTR == null || actualTRPersonaliser == null) + { + LogFormatted("Failed grabbing Instance"); + return false; + } + + //If we get this far we can set up the local object and its methods/functions + LogFormatted_DebugOnly("Got Instance, Creating Wrapper Objects"); + TexRepPersonaliser = new TRPersonaliserAPI(actualTRPersonaliser); + + _TRWrapped = true; + return true; + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + /// + /// The Type that is an analogue of the real Texture replacer. This lets you access all the API-able properties and Methods of Texture Replacer + /// + public class TRPersonaliserAPI + { + internal TRPersonaliserAPI(Object TexRepPersonaliser) + { + //store the actual object + APIactualTRPersonaliser = TexRepPersonaliser; + + //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 + //LogFormatted("Getting APIReady Object"); + //APIReadyField = TRType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); + //LogFormatted("Success: " + (APIReadyField != null).ToString()); + + //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPLE HERE + //Methods + LogFormatted_DebugOnly("Getting personalise Method"); + personaliseIvaMethod = TRPersonaliserType.GetMethod("personaliseIva", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (personaliseIvaMethod != null)); + } + + private Object APIactualTRPersonaliser; + + #region Methods + + private MethodInfo personaliseIvaMethod; + + /// + /// Personalise IVA textures of a kerbal + /// + /// The Kerbal reference + /// Success of call + internal void personaliseIva(Kerbal kerbal) + { + try + { + personaliseIvaMethod.Invoke(APIactualTRPersonaliser, new Object[] { kerbal }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke Texture Replacer personaliseIva Method"); + LogFormatted("Exception: {0}", ex); + //throw; + } + } + + #endregion Methods + } + + #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 + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + if (RSTUtils.Utilities.debuggingOn) + 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, Assembly.GetExecutingAssembly().GetName().Name, + MethodBase.GetCurrentMethod().DeclaringType.Name); + Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/APIs/USIWrapper.cs b/Source/APIs/USIWrapper.cs new file mode 100644 index 0000000..b44278e --- /dev/null +++ b/Source/APIs/USIWrapper.cs @@ -0,0 +1,299 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton based of code and concepts from the Kerbal Alarm Clock Mod. Which was licensed under the MIT license. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Debug = UnityEngine.Debug; + +namespace DF +{ + /// + /// The Wrapper class to access USI LS + /// + public class USIWrapper + { + protected static Type USIType; + protected static Type USILifeSupportMgrType; + + protected static Object actualUSI; + + /// + /// This is the USI LS Actual object + /// + /// SET AFTER INIT + /// + public static USIAPI USIActualAPI; + + /// + /// Whether we found the USI LS assembly in the loadedassemblies. + /// + /// SET AFTER INIT + /// + public static Boolean AssemblyExists { get { return USIType != null; } } + + /// + /// Whether we managed to hook the running Instance from the assembly. + /// + /// SET AFTER INIT + /// + public static Boolean InstanceExists { get { return USIActualAPI != null; } } + + /// + /// Whether we managed to wrap all the methods/functions from the instance. + /// + /// SET AFTER INIT + /// + private static Boolean _USIWrapped; + + /// + /// Whether the object has been wrapped + /// + public static Boolean APIReady { get { return _USIWrapped; } } + + /// + /// This method will set up the USI LS object and wrap all the methods/functions + /// + /// + public static Boolean InitUSIWrapper() + { + //reset the internal objects + _USIWrapped = false; + actualUSI = null; + LogFormatted_DebugOnly("Attempting to Grab USI LS Types..."); + + //find the base type + USIType = getType("LifeSupport.LifeSupportScenario"); + + if (USIType == null) + { + return false; + } + + LogFormatted("USI LS Version:{0}", USIType.Assembly.GetName().Version.ToString()); + + //find the LifeSupportManager class type + USILifeSupportMgrType = getType("LifeSupport.LifeSupportManager"); + + if (USILifeSupportMgrType == null) + { + return false; + } + + + //now grab the running instance + LogFormatted_DebugOnly("Got Assembly Types, grabbing Instances"); + + try + { + actualUSI = USILifeSupportMgrType.GetField("instance", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); + } + catch (Exception) + { + LogFormatted("No USI LS LifeSupportManager Instance found"); + //throw; + } + //if (actualUSI == null || actualUSIUntrackKerbal == null) + if (actualUSI == null) + { + LogFormatted("Failed grabbing Instance"); + return false; + } + + + //If we get this far we can set up the local object and its methods/functions + LogFormatted_DebugOnly("Got Instance, Creating Wrapper Objects"); + USIActualAPI = new USIAPI(actualUSI); + //USIIsKerbalTracked = new USIIsKerbalTrackedAPI(actualUSIIsKerbalTracked); + + _USIWrapped = true; + return true; + } + + internal static Type getType(string name) + { + Type type = null; + AssemblyLoader.loadedAssemblies.TypeOperation(t => + + { + if (t.FullName == name) + type = t; + } + ); + + if (type != null) + { + return type; + } + return null; + } + + /// + /// The Type that is an analogue of the real USI LS. This lets you access all the API-able properties and Methods of USI LS + public class USIAPI + { + internal USIAPI(Object a) + { + //store the actual object + APIactualUSI = 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 + //LogFormatted("Getting APIReady Object"); + //APIReadyField = TRType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); + //LogFormatted("Success: " + (APIReadyField != null).ToString()); + + //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPLE HERE + //Methods + LogFormatted_DebugOnly("Getting UntrackKerbal Method"); + USIUntrackKerbalMethod = USILifeSupportMgrType.GetMethod("UntrackKerbal", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (USIUntrackKerbalMethod != null)); + + LogFormatted_DebugOnly("Getting IsKerbalTracked Method"); + USIIsKerbalTrackedMethod = USILifeSupportMgrType.GetMethod("IsKerbalTracked", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (USIIsKerbalTrackedMethod != null)); + + LogFormatted_DebugOnly("Getting UntrackVessel Method"); + USIUntrackVesselMethod = USILifeSupportMgrType.GetMethod("UntrackVessel", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (USIUntrackVesselMethod != null)); + + LogFormatted_DebugOnly("Getting IsVesselTracked Method"); + USIIsVesselTrackedTrackedMethod = USILifeSupportMgrType.GetMethod("IsVesselTracked", BindingFlags.Public | BindingFlags.Instance); + LogFormatted_DebugOnly("Success: " + (USIIsVesselTrackedTrackedMethod != null)); + } + + private Object APIactualUSI; + + #region Methods + + private MethodInfo USIUntrackKerbalMethod; + + /// + /// Untrack a kerbal in USI LS + /// + /// A string containing the kerbal's name + internal void UntrackKerbal(string kerbal) + { + try + { + USIUntrackKerbalMethod.Invoke(APIactualUSI, new Object[] { kerbal }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke USI LS UntrackKerbal Method"); + LogFormatted("Exception: {0}", ex); + //throw; + } + } + + private MethodInfo USIIsKerbalTrackedMethod; + + /// + /// Untrack a kerbal in USI LS + /// + /// A string containing the kerbal's name + internal bool IsKerbalTracked(string kerbal) + { + try + { + return (bool)USIIsKerbalTrackedMethod.Invoke(APIactualUSI, new Object[] { kerbal }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke USI LS IsKerbalTracked Method"); + LogFormatted("Exception: {0}", ex); + return true; + //throw; + } + } + + private MethodInfo USIIsVesselTrackedTrackedMethod; + + /// + /// Untrack a vessel in USI LS + /// + /// A string containing the vessel's id + internal bool IsVesselTracked(string vesselId) + { + try + { + return (bool)USIIsVesselTrackedTrackedMethod.Invoke(APIactualUSI, new Object[] { vesselId }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke USI LS IsVesselTracked Method"); + LogFormatted("Exception: {0}", ex); + return true; + //throw; + } + } + + private MethodInfo USIUntrackVesselMethod; + + /// + /// Untrack a vessel in USI LS + /// + /// A string containing the vessel's Id + internal void UntrackVessel(string vesselId) + { + try + { + USIUntrackVesselMethod.Invoke(APIactualUSI, new Object[] { vesselId }); + } + catch (Exception ex) + { + LogFormatted("Unable to invoke USI LS UntrackVessel Method"); + LogFormatted("Exception: {0}", ex); + //throw; + } + } + + #endregion Methods + } + + + #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 + internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) + { + if (RSTUtils.Utilities.debuggingOn) + 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, Assembly.GetExecutingAssembly().GetName().Name, + MethodBase.GetCurrentMethod().DeclaringType.Name); + Debug.Log(strMessageLine); + } + + #endregion Logging Stuff + } +} \ No newline at end of file diff --git a/Source/DFAlarmInfo.cs b/Source/DFAlarmInfo.cs new file mode 100644 index 0000000..4f90403 --- /dev/null +++ b/Source/DFAlarmInfo.cs @@ -0,0 +1,123 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + */ + +using System; +using System.Collections.Generic; +using RSTUtils; + +namespace DF +{ + internal class AlarmInfo + { + //This class stores Info about Kerbal Alarm Clock Alarms that are associated with DeepFreeze Vessels. + //VesselID - VesselID of the Vessel this Alarm is attached to + //string Name - The name of the KAC Alarm + //AlarmType - The type of KAC Alarm + //Notes - The KAC Alarm notes, has THAW xxxx and FREEZE xxxx lines added to it for Freeze and Thaw DeepFreeze commands to execute when the alarm triggers. + //AlarmTime - The time of the Alarm from KAC + //AlarmMargin - The margin of the Alarm from KAC + //FrzKerbals - a List of kerbals to freeze from the vessel when the alarm fires. + //ThwKerbals - a List of kerbals to thaw from the vessel when the alarm fires. + //AlarmExecute - Bool is true when Alarm has fired from KAC and we are processing it in DeepFreeze. + // + internal const string ConfigNodeName = "AlarmInfo"; + + internal Guid VesselID; + internal string Name; + internal KACWrapper.KACAPI.AlarmTypeEnum AlarmType; + internal string Notes; + internal double AlarmTime; + internal double AlarmMargin; + internal List FrzKerbals; + internal List ThwKerbals; + internal bool AlarmExecute; + + internal AlarmInfo(string Name, Guid vesselID) + { + this.Name = Name; + VesselID = vesselID; + FrzKerbals = new List(); + ThwKerbals = new List(); + } + + internal static AlarmInfo Load(ConfigNode node) + { + Guid vesselID = Utilities.GetNodeValue(node, "vesselID"); + string Name = ""; + node.TryGetValue("Name", ref Name); + + AlarmInfo info = new AlarmInfo(Name, vesselID); + + info.AlarmType = Utilities.GetNodeValue(node, "AlarmType", KACWrapper.KACAPI.AlarmTypeEnum.Raw); + node.TryGetValue("Notes", ref info.Notes); + node.TryGetValue("AlarmTime", ref info.AlarmTime); + node.TryGetValue("AlarmMargin", ref info.AlarmMargin); + node.TryGetValue("AlarmExecute", ref info.AlarmExecute); + + + string frzkbllst = ""; + node.TryGetValue("FrzKerbals", ref frzkbllst); + string thwkbllst = ""; + node.TryGetValue("ThwKerbals", ref thwkbllst); + + string[] frzStrings = frzkbllst.Split(','); + if (frzStrings.Length > 0) + { + for (int i = 0; i < frzStrings.Length; i++) + { + info.FrzKerbals.Add(frzStrings[i]); + } + } + string[] thwStrings = thwkbllst.Split(','); + if (thwStrings.Length > 0) + { + for (int i = 0; i < thwStrings.Length; i++) + { + if (thwStrings[i].Length > 0) + info.ThwKerbals.Add(thwStrings[i]); + } + } + return info; + } + + internal ConfigNode Save(ConfigNode config) + { + ConfigNode node = config.AddNode(ConfigNodeName); + node.AddValue("vesselID", VesselID); + node.AddValue("Name", Name); + node.AddValue("AlarmType", AlarmType.ToString()); + node.AddValue("Notes", Notes); + node.AddValue("AlarmTime", AlarmTime); + node.AddValue("AlarmMargin", AlarmMargin); + node.AddValue("AlarmExecute", AlarmExecute); + string frzkbllst = string.Join(",", FrzKerbals.ToArray()); + node.AddValue("FrzKerbals", frzkbllst); + string thwkbllst = string.Join(",", ThwKerbals.ToArray()); + node.AddValue("ThwKerbals", thwkbllst); + return node; + } + + internal void ClearFrzKerbals() + { + FrzKerbals.Clear(); + } + + internal void ClearThwKerbals() + { + ThwKerbals.Clear(); + } + } +} \ No newline at end of file diff --git a/Source/DFEditorFilter.cs b/Source/DFEditorFilter.cs new file mode 100644 index 0000000..5750060 --- /dev/null +++ b/Source/DFEditorFilter.cs @@ -0,0 +1,162 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System.Collections.Generic; +using KSP.UI.Screens; +using RUI.Icons.Selectable; +using UnityEngine; +using KSP.Localization; + +namespace DF +{ + [KSPAddon(KSPAddon.Startup.MainMenu, true)] + public class DFEditorFilter : MonoBehaviour + { + // This class ass a Filter Icon to the Editor to show DeepFreeze Parts + // which currently consist of any partprefab that has component DeepFreezer (All the freezer parts) + // and the GlykerolTankRadial. + private static List avPartItems = new List(); + public static DFEditorFilter Instance; + internal string category = "Filter by Function"; + internal string subCategoryTitle = "DeepFreeze Items"; + + //internal string iconName = "R&D_node_icon_evatech"; + //create and the icons + //private Texture2D icon_DeepFreeze_Editor; + + internal string iconName = "DeepFreezeEditor"; + internal bool filter = true; + + public void Awake() + { + if (Instance != null) + { + Destroy(this); + } + Instance = this; + DontDestroyOnLoad(this); + } + + public void Setup() + { + Debug.Log("DFEditorFilter Start"); + RemoveSubFilter(); + AddPartUtilitiesCat(); + GameEvents.onGUIEditorToolbarReady.Remove(SubCategories); + + + if (!HighLogic.CurrentGame.Parameters.CustomParams().EditorFilter) + { + Debug.Log("EditorFilter Option is Off"); + return; + } + + + Debug.Log("EditorFilter Option is On"); + DFMMCallBack(); + RemovePartUtilitiesCat(); + GameEvents.onGUIEditorToolbarReady.Add(SubCategories); + /* + //Attempt to add Module Manager callback - find the base type + System.Type MMType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "ModuleManager.MMPatchLoader"); + if (MMType != null) + { + MethodInfo MMPatchLoaderInstanceMethod = MMType.GetMethod("get_Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + if (MMPatchLoaderInstanceMethod != null) + { + object actualMM = MMPatchLoaderInstanceMethod.Invoke(null, + BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, null, null, null); + MethodInfo MMaddPostPatchCallbackMethod = MMType.GetMethod("addPostPatchCallback", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + if (actualMM != null && MMaddPostPatchCallbackMethod != null) + MMaddPostPatchCallbackMethod.Invoke(actualMM, new object[] { this.DFMMCallBack() }); + } + + }*/ + //DFMMCallBack(); + Debug.Log("DFEditorFilter Awake Complete"); + } + + public bool DFMMCallBack() + { + Debug.Log("DFEDitorFilter DFMMCallBack"); + avPartItems.Clear(); + foreach (AvailablePart avPart in PartLoader.LoadedPartsList) + { + if (!avPart.partPrefab) continue; + DeepFreezer moduleItem = avPart.partPrefab.GetComponent(); + if (avPart.name == "GlykerolTankRadial" || avPart.name == "DF.Glykerol.Tank" || moduleItem) + { + avPartItems.Add(avPart); + } + } + Debug.Log("DFEDitorFilter DFMMCallBack end"); + return true; + } + + private void RemoveSubFilter() + { + if (PartCategorizer.Instance != null) + { + PartCategorizer.Category Filter = PartCategorizer.Instance.filters.Find(f => f.button.categoryName == category); + if (Filter != null) + { + PartCategorizer.Category subFilter = Filter.subcategories.Find(f => f.button.categoryName == subCategoryTitle); + if (subFilter != null) + { + subFilter.DeleteSubcategory(); + } + } + } + } + + private void RemovePartUtilitiesCat() + { + foreach (AvailablePart avPart in avPartItems) + { + avPart.category = PartCategories.none; + } + } + + private void AddPartUtilitiesCat() + { + foreach (AvailablePart avPart in avPartItems) + { + avPart.category = PartCategories.Utility; + } + } + + private bool EditorItemsFilter(AvailablePart avPart) + { + if (avPartItems.Contains(avPart)) + { + return true; + } + return false; + } + + private void SubCategories() + { + RemoveSubFilter(); + Icon filterDeepFreeze = new Icon("DeepFreezeEditor", Textures.DeepFreeze_Editor, Textures.DeepFreeze_Editor, true); + PartCategorizer.Category Filter = PartCategorizer.Instance.filters.Find(f => f.button.categoryName == category); + PartCategorizer.AddCustomSubcategoryFilter(Filter, subCategoryTitle, Localizer.Format("#autoLOC_DF_00107"), filterDeepFreeze, p => EditorItemsFilter(p)); + } + } +} \ No newline at end of file diff --git a/Source/DFEnums.cs b/Source/DFEnums.cs new file mode 100644 index 0000000..c1a4fbe --- /dev/null +++ b/Source/DFEnums.cs @@ -0,0 +1,32 @@ +/* + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright(C) 2013 Squad.See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license.See + * for full details. + * + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DF +{ + public enum DoorState + { + OPEN, + CLOSED, + OPENING, + CLOSING, + UNKNOWN + } +} diff --git a/Source/DFExtDoorMgr.cs b/Source/DFExtDoorMgr.cs new file mode 100644 index 0000000..de04194 --- /dev/null +++ b/Source/DFExtDoorMgr.cs @@ -0,0 +1,93 @@ +/* + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright(C) 2013 Squad.See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license.See + * for full details. + * + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RSTUtils; + +namespace DF +{ + public class DFExtDoorMgr : InternalModule + { + private DeepFreezer Freezer; + + public override void OnUpdate() + { + base.OnUpdate(); + if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && FlightGlobals.ActiveVessel != null) + { + if (Freezer == null) + { + Freezer = part.FindModuleImplementing(); + Utilities.Log_Debug("DFExtDoorMgr OnUpdate Set part " + part.name); + } + } + } + + public void ButtonExtDoor(bool state) + { + if (Freezer == null) + { + Freezer = part.FindModuleImplementing(); + Utilities.Log_Debug("DFExtDoorMgr buttonExtDoorState set part " + part.name); + } + if (Freezer == null) return; // If freezer is still null just return + if (!Freezer.ExternalDoorActive) return; // if freezer doesn't have an external door just return. + + if (Freezer._externaldoorstate == DoorState.OPEN) + { + //Door is open so we trigger a closedoor. + Freezer.eventCloseDoors(); + Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired triggered eventCloseDoors"); + } + else + { + if (Freezer._externaldoorstate == DoorState.CLOSED) + { + //Door is closed so we trigger a opendoor. + Freezer.eventOpenDoors(); + Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired triggered eventOpenDoors"); + } + else + { + // door already opening or closing... + Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired but door state is opening, closing or unknown"); + } + } + } + + public bool ButtonExtDoorState() + { + // Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoorState fired"); + if (Freezer == null) + { + Freezer = part.FindModuleImplementing(); + Utilities.Log_Debug("DFExtDoorMgr buttonExtDoorState set part " + part.name); + } + if (Freezer == null) return false; // if freezer still null return false + if (!Freezer.ExternalDoorActive) return false; // if freezer doesn't have an external door just return. + if (Freezer._externaldoorstate == DoorState.CLOSED || Freezer._externaldoorstate == DoorState.CLOSING || Freezer._externaldoorstate == DoorState.UNKNOWN) + { + Utilities.Log_Debug("DFExtDoorMgr Door is closed or closing or unknown return state false"); + return false; + } + Utilities.Log_Debug("DFExtDoorMgr Door is open or opening return state true"); + return true; + } + } +} diff --git a/Source/DFGameSettings.cs b/Source/DFGameSettings.cs new file mode 100644 index 0000000..2952571 --- /dev/null +++ b/Source/DFGameSettings.cs @@ -0,0 +1,238 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using RSTUtils; + +namespace DF +{ + internal class DFGameSettings + { + // This class stores the DeepFreeze Gamesettings config node. + // which includes the following Dictionaries + // KnownFrozenKerbals - all known frozen kerbals in the current save game + // knownVessels - all vessels in the save game that contain a DeepFreezer partmodule + // knownFreezerPArts - all parts in the save game that contain a DeepFreezer partmodule + // knownKACAlarms = all Kerbal Alarm Clock alarms that are associated with a DeppFreezer knownVessels entry + + public const string configNodeName = "DFGameSettings"; + public bool Enabled; + internal Dictionary KnownFrozenKerbals; + internal Dictionary knownVessels; + internal Dictionary knownFreezerParts; + internal Dictionary knownKACAlarms; + + internal DFGameSettings() + { + Enabled = true; + KnownFrozenKerbals = new Dictionary(); + knownVessels = new Dictionary(); + knownFreezerParts = new Dictionary(); + knownKACAlarms = new Dictionary(); + } + + internal void Load(ConfigNode node) + { + KnownFrozenKerbals.Clear(); + knownVessels.Clear(); + knownFreezerParts.Clear(); + knownKACAlarms.Clear(); + + if (node.HasNode(configNodeName)) + { + ConfigNode DFsettingsNode = node.GetNode(configNodeName); + DFsettingsNode.TryGetValue("Enabled", ref Enabled); + + KnownFrozenKerbals.Clear(); + var kerbalNodes = DFsettingsNode.GetNodes(KerbalInfo.ConfigNodeName); + foreach (ConfigNode kerbalNode in kerbalNodes) + { + if (kerbalNode.HasValue("kerbalName")) + { + string id = kerbalNode.GetValue("kerbalName"); + Utilities.Log_Debug("DFGameSettings Loading kerbal = " + id); + KerbalInfo kerbalInfo = KerbalInfo.Load(kerbalNode); + KnownFrozenKerbals.Add(id, kerbalInfo); + } + } + Utilities.Log_Debug("DFGameSettings finished loading FrozenKerbals"); + knownVessels.Clear(); + var vesselNodes = DFsettingsNode.GetNodes(VesselInfo.ConfigNodeName); + foreach (ConfigNode vesselNode in vesselNodes) + { + if (vesselNode.HasValue("Guid")) + { + Guid id = new Guid(vesselNode.GetValue("Guid")); + Utilities.Log_Debug("DFGameSettings Loading Guid = " + id); + VesselInfo vesselInfo = VesselInfo.Load(vesselNode); + knownVessels[id] = vesselInfo; + } + } + Utilities.Log_Debug("DFGameSettings finished loading KnownVessels"); + knownFreezerParts.Clear(); + var partNodes = DFsettingsNode.GetNodes(PartInfo.ConfigNodeName); + foreach (ConfigNode partNode in partNodes) + { + if (partNode.HasValue("flightID")) + { + uint id = uint.Parse(partNode.GetValue("flightID")); + Utilities.Log_Debug("DFGameSettings Loading flightID = " + id); + PartInfo partInfo = PartInfo.Load(partNode); + knownFreezerParts[id] = partInfo; + } + } + Utilities.Log_Debug("DFGameSettings finished loading KnownParts"); + knownKACAlarms.Clear(); + var KACAlarmNodes = DFsettingsNode.GetNodes(AlarmInfo.ConfigNodeName); + foreach (ConfigNode alarmNode in KACAlarmNodes) + { + if (alarmNode.HasValue("alarmID")) + { + string alarmID = alarmNode.GetValue("alarmID"); + Utilities.Log_Debug("DFGameSettings Loading alarmID = " + alarmID); + AlarmInfo alarmInfo = AlarmInfo.Load(alarmNode); + knownKACAlarms[alarmID] = alarmInfo; + } + } + SyncDictionaries(); + } + Utilities.Log_Debug("DFGameSettings Loading Complete"); + } + + internal void Save(ConfigNode node) + { + ConfigNode settingsNode; + if (node.HasNode(configNodeName)) + { + settingsNode = node.GetNode(configNodeName); + } + else + { + settingsNode = node.AddNode(configNodeName); + } + + settingsNode.AddValue("Enabled", Enabled); + + foreach (var entry in KnownFrozenKerbals) + { + ConfigNode vesselNode = entry.Value.Save(settingsNode); + Utilities.Log_Debug("DFGameSettings Saving kerbal = " + entry.Key); + vesselNode.AddValue("kerbalName", entry.Key); + } + + foreach (var entry in knownVessels) + { + ConfigNode vesselNode = entry.Value.Save(settingsNode); + Utilities.Log_Debug("DFGameSettings Saving Guid = " + entry.Key); + vesselNode.AddValue("Guid", entry.Key); + } + + foreach (var entry in knownFreezerParts) + { + ConfigNode partNode = entry.Value.Save(settingsNode); + Utilities.Log_Debug("DFGameSettings Saving part flightID = " + entry.Key); + partNode.AddValue("flightID", entry.Key); + } + + foreach (var entry in knownKACAlarms) + { + ConfigNode alarmNode = entry.Value.Save(settingsNode); + Utilities.Log_Debug("DFGameSettings Saving KACAlarm = " + entry.Key); + alarmNode.AddValue("alarmID", entry.Key); + } + + Utilities.Log_Debug("DFGameSettings Saving Complete"); + } + + internal void DmpKnownFznKerbals() + { + Utilities.Log_Debug("Dump of KnownFrozenKerbals"); + if (!KnownFrozenKerbals.Any()) + { + Utilities.Log_Debug("KnownFrozenKerbals is EMPTY."); + } + else + { + foreach (KeyValuePair kerbal in KnownFrozenKerbals) + { + Utilities.Log_Debug("Kerbal = " + kerbal.Key + " status = " + kerbal.Value.status + " type = " + + kerbal.Value.type + " vesselID = " + kerbal.Value.vesselID); + } + } + } + + internal void DmpKnownVessels() + { + Utilities.Log_Debug("Dump of KnownVessels"); + if (!knownVessels.Any()) + { + Utilities.Log_Debug("KnownVessels is EMPTY."); + } + else + { + foreach (KeyValuePair vessel in knownVessels) + { + Utilities.Log_Debug("Vessel = " + vessel.Key + " Name = " + vessel.Value.vesselName + " ,crew = " + + vessel.Value.numCrew + " ,frozencrew = " + vessel.Value.numFrznCrew); + } + } + } + + internal void SyncDictionaries() + { + List frznkerbalstoDelete = new List(); + List freezerPartstoDelete = new List(); + //loop through all known frozen kerbals. Check there is a knownFreezerParts entry for them. If not, remove them. + foreach (KeyValuePair FrznKerbal in KnownFrozenKerbals) + { + if (!knownFreezerParts.ContainsKey(FrznKerbal.Value.partID)) + { + //Couldn't find one. Check the Roster, if they are in the roster set them to Missing. + //Remove from Dictionary + if (HighLogic.CurrentGame.CrewRoster != null) + { + var Kerbal = HighLogic.CurrentGame.CrewRoster.Crew.FirstOrDefault(a => a.name == FrznKerbal.Key); + if (Kerbal != null) + { + if (Kerbal.type == ProtoCrewMember.KerbalType.Crew || + Kerbal.type == ProtoCrewMember.KerbalType.Unowned) + { + //set them to MIA + } + } + } + frznkerbalstoDelete.Add(FrznKerbal.Key); + Utilities.Log("Found orphaned Frozen Kerbal Entry in Database for " + FrznKerbal.Key +" Deleting entry"); + } + } + frznkerbalstoDelete.ForEach(id => KnownFrozenKerbals.Remove(id)); + //loop through all known frozen Freezer Parts. Check there is a knownVessels entry for them. If not, remove them. + foreach (KeyValuePair FrzrPart in knownFreezerParts) + { + if (!knownVessels.ContainsKey(FrzrPart.Value.vesselID)) + { + //Couldn't find one. Remove from Dictionary + freezerPartstoDelete.Add(FrzrPart.Key); + Utilities.Log("Found orphaned Freezer Part Entry in Database for " + FrzrPart.Key + " Deleting entry"); + } + } + freezerPartstoDelete.ForEach(id => knownFreezerParts.Remove(id)); + } + } +} \ No newline at end of file diff --git a/Source/DFInstalledMods.cs b/Source/DFInstalledMods.cs new file mode 100644 index 0000000..36741b2 --- /dev/null +++ b/Source/DFInstalledMods.cs @@ -0,0 +1,224 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using RSTUtils; + +namespace DF +{ + internal class DFInstalledMods + { + // Class used to check what Other mods we are interested in are installed. + + private static Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + private static List modInfo; + + internal class ModInfo + { + public string name; + public bool alreadyChecked; + public bool installed; + + public ModInfo(string name) + { + this.name = name; + } + } + + internal static bool IsSMInstalled + { + get + { + ModInfo info = GetInfo("ShipManifest"); + if (info.alreadyChecked) + { + return info.installed; + } + else + { + + } + return IsModInstalled("ShipManifest"); + } + } + + internal static bool IsRTInstalled + { + get + { + return IsModInstalled("RemoteTech"); + } + } + + internal static bool IsUSILSInstalled + { + get + { + return IsModInstalled("USILifeSupport"); + } + } + + internal static bool IsSnacksInstalled + { + get + { + return IsModInstalled("Snacks"); + } + } + + internal static bool IsTACLSInstalled + { + get + { + return IsModInstalled("TacLifeSupport"); + } + } + + internal static bool IsRPMInstalled + { + get + { + return IsModInstalled("RasterPropMonitor"); + } + } + + internal static bool IsJSITransparentPodsInstalled + { + get + { + return IsModInstalled("JSIAdvTransparentPods"); + } + } + + internal static bool IsBGPInstalled + { + get + { + return IsModInstalled("BackgroundProcessing"); + } + } + + internal static bool IsBGRInstalled + { + get + { + return IsModInstalled("BackgroundResources"); + } + } + + internal static bool IsTexReplacerInstalled + { + get + { + return IsModInstalled("TextureReplacer"); + } + } + + internal static bool IskerbalismInstalled + { + get + { + return IsModInstalled("Kerbalism"); + } + } + + internal static bool IsModInstalled(string assemblyName) + { + ModInfo info = GetInfo(assemblyName); + if (info.alreadyChecked) + { + return info.installed; + } + + try + { + Assembly assembly = (from a in assemblies + where a.FullName.Split(',')[0] == assemblyName + select a).First(); + info.alreadyChecked = true; + info.installed = assembly != null; + return info.installed; + } + catch + { + return false; + } + } + + internal static ModInfo GetInfo(string name) + { + if (modInfo == null) + { + modInfo = new List(); + } + for (int i = 0; i < modInfo.Count; i++) + { + ModInfo info = modInfo[i]; + if (modInfo[i].name == name) + { + return modInfo[i]; + } + } + ModInfo newInfo = new ModInfo(name); + modInfo.Add(newInfo); + return newInfo; + } + + + internal static bool RTVesselConnected(Guid id) + { + bool RTVslConnected = false; + try + { + if (IsRTInstalled && RTWrapper.APIReady) + { + //RTVslConnected = (RemoteTech.API.API.HasLocalControl(id) || RemoteTech.API.API.HasAnyConnection(id)); + RTVslConnected = RTWrapper.RTactualAPI.HasLocalControl(id) || RTWrapper.RTactualAPI.HasAnyConnection(id); + //Utilities.Log_Debug("vessel " + id + "haslocal " + RemoteTech.API.API.HasLocalControl(id) + " has any " + RemoteTech.API.API.HasAnyConnection(id)); + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreeze Exception attempting to check RemoteTech connections. Report this error on the Forum Thread."); + Utilities.Log("DeepFreeze Err: " + ex); + } + return RTVslConnected; + } + + internal static double RTVesselDelay + { + get + { + double RTVslDelay = 0f; + try + { + //RTVslDelay = RemoteTech.API.API.GetShortestSignalDelay(FlightGlobals.ActiveVessel.id); + RTVslDelay = RTWrapper.RTactualAPI.GetShortestSignalDelay(FlightGlobals.ActiveVessel.id); + } + catch (Exception ex) + { + Utilities.Log("DeepFreeze Exception attempting to check RemoteTech VesselDelay. Report this error on the Forum Thread."); + Utilities.Log("DeepFreeze Err: " + ex); + } + return RTVslDelay; + } + } + } +} \ No newline at end of file diff --git a/Source/DFIntMemory.cs b/Source/DFIntMemory.cs new file mode 100644 index 0000000..0dadaa1 --- /dev/null +++ b/Source/DFIntMemory.cs @@ -0,0 +1,1557 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Collections.Generic; +using BackgroundResources; +using KSP.UI.Screens; +using PreFlightTests; +using RSTUtils; +using UnityEngine; +using KSP.Localization; + +namespace DF +{ + internal class DFIntMemory : MonoBehaviour + { + // The DeepFreeze Internal memory class. + // this class maintains the information in the knownVessels, knownFreezerParts and knownKACalarms dictionaries. + // It also Executes KAC Alarms when they occur and have DeepFreeze events to execute. + // and controls the Alternate DeepFreeze IVA cameras and Messages when in IVA. + public static DFIntMemory Instance { get; private set; } + + public class VslFrzrCams + { + public Transform FrzrCamTransform { get; set; } + public InternalModel FrzrCamModel { get; set; } + public int FrzrCamSeatIndex { get; set; } + public string FrzrCamPartName { get; set; } + public DeepFreezer FrzrCamPart { get; set; } + + public VslFrzrCams(Transform frzrcamTransform, InternalModel frzrcamModel, int frzrcamSeatIndex, string frzrcamPartName, DeepFreezer frzrcamPart) + { + FrzrCamTransform = frzrcamTransform; + FrzrCamModel = frzrcamModel; + FrzrCamSeatIndex = frzrcamSeatIndex; + FrzrCamPartName = frzrcamPartName; + FrzrCamPart = frzrcamPart; + } + } + + internal List DpFrzrActVsl = new List(); + internal bool ActVslHasDpFrezr; + internal Guid ActVslID; + internal bool BGPinstalled; + internal bool BGRinstalled; + internal double invalidKACGUIDItems; + internal int ActFrzrCamPart = 0; + internal List ActFrzrCams = new List(); //This array of transforms stores the transforms for the cryopod cameras for the active vessel. + internal int lastFrzrCam; //Index of last frzrcam used. + private KeyCode keyFrzrCam = (KeyCode)100; //Keycode for frzrcam. Loaded from settings. Default is n + private KeyCode keyNxtFrzrCam = (KeyCode)110; //Keycode for next frzrcam. Loaded from settings. Default is n + private KeyCode keyPrvFrzrCam = (KeyCode)98; //Keycode for previous frzrcam. Loaded from settings. Default is b + internal ScreenMessage IVAKerbalName, IVAkerbalPart, IVAkerbalPod; // used for the bottom right screen messages + //private bool refreshPortraits; // set to true after a vessel coupling has occurred, a timer waits 3 secnds then refreshes the portraits cams. + //private double refreshPortraitsTimer; // the timer for the previous var + private int AllVslsErrorCount; //stop log spam + private List ComakeysToDelete = new List(); + private List> comaKerbals = new List>(); + private double currentTime, lastFixedUpdateTime, checkVesselUpdateTime, checkVesselComaTime; + private List TmpDpFrzrActVsl = new List(); + private List allVessels = new List(); + private List vesselsToDelete = new List(); + private List partsToDelete = new List(); + private Dictionary knownVessels = new Dictionary(); + private Guid vesselId; + private Vessel vessel; + private int crewCapacity; + private VesselInfo vesselInfo; + private PartInfo partInfo; + private List DpFrzrLoadedVsl = new List(); + private bool freezeThawActive; + /// + /// True if a Freeze or Thaw is active in any DeepFreezer + /// + public static bool FreezeThawActive + { + get + { + if (Instance != null) + { + return Instance.freezeThawActive; + } + + return false; + } + } + + protected DFIntMemory() + { + //Utilities.Log("DFIntMemory Constructor"); + Instance = this; + } + + #region MonoBehavior + private void Awake() + { + Utilities.Log_Debug("DFIntMemory Awake"); + KACWrapper.InitKACWrapper(); //KAC Mod + if (KACWrapper.APIReady) + KACWrapper.KAC.onAlarmStateChanged += KAC_onAlarmStateChanged; + BGPinstalled = DFInstalledMods.IsBGPInstalled; //Background Processing Mod + BGRinstalled = DFInstalledMods.IsBGRInstalled; //Background Resources Mod + GameEvents.onVesselRename.Add(onVesselRename); + GameEvents.onVesselChange.Add(onVesselChange); + GameEvents.onVesselLoaded.Add(onVesselLoad); + GameEvents.onVesselCreate.Add(onVesselCreate); + GameEvents.onPartCouple.Add(onPartCouple); + GameEvents.onGUIEngineersReportReady.Add(AddTests); + if (DFGameEvents.onKerbalFreezing != null) + { + DFGameEvents.onKerbalFreezing.Add(ThawFreezeStart); + } + if (DFGameEvents.onKerbalThawing != null) + { + DFGameEvents.onKerbalThawing.Add(ThawFreezeStart); + } + if (DFGameEvents.onKerbalFrozen != null) + { + DFGameEvents.onKerbalFrozen.Add(ThawFreezeEnd); + } + if (DFGameEvents.onKerbalThaw != null) + { + DFGameEvents.onKerbalThaw.Add(ThawFreezeEnd); + } + if (DFGameEvents.onKerbalFreezeAbort != null) + { + DFGameEvents.onKerbalFreezeAbort.Add(ThawFreezeAbort); + } + if (DFGameEvents.onKerbalThawAbort != null) + { + DFGameEvents.onKerbalThawAbort.Add(ThawFreezeAbort); + } + + try + { + keyFrzrCam = (KeyCode)DeepFreeze.Instance.DFsettings.internalFrzrCamCode; + keyNxtFrzrCam = (KeyCode)DeepFreeze.Instance.DFsettings.internalNxtFrzrCamCode; + keyPrvFrzrCam = (KeyCode)DeepFreeze.Instance.DFsettings.internalPrvFrzrCamCode; + if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null) + onVesselChange(FlightGlobals.ActiveVessel); + } + catch (Exception) + { + Utilities.Log_Debug("Invalid Freezer Cam Code in settings. Settings value=" + DeepFreeze.Instance.DFsettings.internalFrzrCamCode); + keyFrzrCam = (KeyCode)100; + } + Utilities.Log_Debug("DFIntMemory end Awake"); + } + + private void Start() + { + Utilities.Log_Debug("DFIntMemory startup"); + ChkUnknownFrozenKerbals(); + ChkActiveFrozenKerbals(); + DeepFreeze.Instance.DFgameSettings.DmpKnownFznKerbals(); + resetFreezerCams(); + if (Utilities.GameModeisFlight) + { + if (DFInstalledMods.IsTexReplacerInstalled) + { + TRWrapper.InitTRWrapper(); + } + if (DFInstalledMods.IsUSILSInstalled) + { + USIWrapper.InitUSIWrapper(); + } + if (DFInstalledMods.IsSMInstalled) + { + SMWrapper.InitSMWrapper(); + } + } + if (DFInstalledMods.IsRTInstalled) + { + RTWrapper.InitTRWrapper(); + } + currentTime = Planetarium.GetUniversalTime(); + lastFixedUpdateTime = currentTime; + vesselInfo = new VesselInfo("testVessel", currentTime); + partInfo = new PartInfo(Guid.Empty, "testPart", currentTime); + } + + private void OnDestroy() + { + Utilities.Log_Debug("DFIntMemory OnDestroy"); + //destroy the event hook for KAC + if (KACWrapper.APIReady) + KACWrapper.KAC.onAlarmStateChanged -= KAC_onAlarmStateChanged; + GameEvents.onVesselRename.Remove(onVesselRename); + GameEvents.onVesselChange.Remove(onVesselChange); + GameEvents.onVesselLoaded.Remove(onVesselLoad); + GameEvents.onVesselCreate.Remove(onVesselCreate); + GameEvents.onPartCouple.Remove(onPartCouple); + GameEvents.onGUIEngineersReportReady.Remove(AddTests); + if (DFGameEvents.onKerbalFreezing != null) + { + DFGameEvents.onKerbalFreezing.Remove(ThawFreezeStart); + } + if (DFGameEvents.onKerbalThawing != null) + { + DFGameEvents.onKerbalThawing.Remove(ThawFreezeStart); + } + if (DFGameEvents.onKerbalFrozen != null) + { + DFGameEvents.onKerbalFrozen.Remove(ThawFreezeEnd); + } + if (DFGameEvents.onKerbalThaw != null) + { + DFGameEvents.onKerbalThaw.Remove(ThawFreezeEnd); + } + if (DFGameEvents.onKerbalFreezeAbort != null) + { + DFGameEvents.onKerbalFreezeAbort.Remove(ThawFreezeAbort); + } + if (DFGameEvents.onKerbalThawAbort != null) + { + DFGameEvents.onKerbalThawAbort.Remove(ThawFreezeAbort); + } + } + + private void Update() + { + if (!HighLogic.LoadedSceneIsFlight) + return; + //For some reason when we Freeze a Kerbal and switch to the Internal camera (if in IVA mode) the cameramanager gets stuck. + //If the user hits the camera mode key while in Internal camera mode this will kick them out to flight + if (GameSettings.CAMERA_MODE.GetKeyDown() && Utilities.IsInInternal) + { + CameraManager.Instance.SetCameraFlight(); + } + + //Check if the FreezerCam references have disappeared and if they have reset. + if (ActFrzrCams.Count > 0) + { + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform == null || ActFrzrCams[lastFrzrCam].FrzrCamModel == null) + { + resetFreezerCams(); + } + } + + if (ActVslHasDpFrezr) + { + //If user hits Modifier Key - D switch to freezer cams. + if (GameSettings.MODIFIER_KEY.GetKey() && Input.GetKeyDown(keyFrzrCam) && ActFrzrCams.Count > 0 && !Utilities.StockOverlayCamIsOn) + { + Utilities.Log_Debug("User hit InternalCamera modifier keys lastFrzrCam=" + lastFrzrCam); + if (Utilities.IsInIVA) + { + Utilities.Log_Debug("Vessel is in IVA, looking for active kerbal"); + Kerbal activeKerbal; + + activeKerbal = CameraManager.Instance.IVACameraActiveKerbal; + if (activeKerbal != null) + { + int CamIndex = -1; + CamIndex = ActFrzrCams.FindIndex(a => a.FrzrCamPart == activeKerbal.InPart && a.FrzrCamSeatIndex == activeKerbal.protoCrewMember.seatIdx); + if (CamIndex != -1) + { + lastFrzrCam = CamIndex; + Utilities.Log_Debug("Vessel was in IVA so Set lastFrzrCam to " + ActFrzrCams[lastFrzrCam].FrzrCamPartName + " " + ActFrzrCams[lastFrzrCam].FrzrCamSeatIndex); + } + } + } + // If we have gone outside the bounds of the camera list, reset to index 0. + if (lastFrzrCam > ActFrzrCams.Count) + { + lastFrzrCam = 0; + } + // Try to set the freezer cam. + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform != null && ActFrzrCams[lastFrzrCam].FrzrCamModel != null) + { + try + { + //CameraManager.Instance.SetCameraMode(CameraManager.CameraMode.Internal); + CameraManager.Instance.SetCameraInternal(ActFrzrCams[lastFrzrCam].FrzrCamModel, ActFrzrCams[lastFrzrCam].FrzrCamTransform); + } + catch (Exception ex) + { + Utilities.Log("Failed to set Internal Camera. " + lastFrzrCam); + if (ActFrzrCams[lastFrzrCam].FrzrCamModel == null) Utilities.Log_Debug("FrzrcamModel is null"); + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform == null) Utilities.Log_Debug("FrzrcamTransform is null"); + Utilities.Log("Err: " + ex); + CameraManager.Instance.SetCameraFlight(); + } + } + else + { + Utilities.Log_Debug("lastFrzrCam is null"); + } + } + + //If user hits n while we are in internal camera mode switch to the next freezer camera. + if (Input.GetKeyDown(keyNxtFrzrCam) && Utilities.IsInInternal) + { + Utilities.Log_Debug("User hit InternalCamera nextCamera key lastFrzrCam=" + lastFrzrCam); + if ((lastFrzrCam == ActFrzrCams.Count - 1) || (lastFrzrCam > ActFrzrCams.Count)) + { + lastFrzrCam = 0; + } + else + { + lastFrzrCam++; + } + Utilities.Log_Debug("CameraCam = " + lastFrzrCam); + + try + { + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform != null && ActFrzrCams[lastFrzrCam].FrzrCamModel != null) + { + CameraManager.Instance.SetCameraInternal(ActFrzrCams[lastFrzrCam].FrzrCamModel, ActFrzrCams[lastFrzrCam].FrzrCamTransform); + } + else + { + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform == null) Utilities.Log_Debug("lastFrzrCamTransform is null"); + if (ActFrzrCams[lastFrzrCam].FrzrCamModel == null) Utilities.Log_Debug("lastFrzrCamModel is null"); + } + } + catch (Exception ex) + { + Utilities.Log("Failed to set Internal Camera."); + if (ActFrzrCams[lastFrzrCam].FrzrCamModel == null) Utilities.Log_Debug("FrzrcamModel is null"); + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform == null) Utilities.Log_Debug("FrzrcamTransform is null"); + Utilities.Log("Err: " + ex); + CameraManager.Instance.SetCameraFlight(); + } + } + + //If user hits b while we are in internal camera mode switch to the previous freezer camera. + if (Input.GetKeyDown(keyPrvFrzrCam) && Utilities.IsInInternal) + { + Utilities.Log_Debug("User hit InternalCamera prevCamera key lastFrzrCam=" + lastFrzrCam); + if (lastFrzrCam <= 0) + { + lastFrzrCam = ActFrzrCams.Count - 1; + } + else + { + lastFrzrCam--; + } + Utilities.Log_Debug("CameraCam = " + lastFrzrCam); + + try + { + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform != null && ActFrzrCams[lastFrzrCam].FrzrCamModel != null) + { + CameraManager.Instance.SetCameraInternal(ActFrzrCams[lastFrzrCam].FrzrCamModel, ActFrzrCams[lastFrzrCam].FrzrCamTransform); + } + else + { + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform == null) Utilities.Log_Debug("lastFrzrCamTransform is null"); + if (ActFrzrCams[lastFrzrCam].FrzrCamModel == null) Utilities.Log_Debug("lastFrzrCamModel is null"); + } + } + catch (Exception ex) + { + Utilities.Log("Failed to set Internal Camera."); + if (ActFrzrCams[lastFrzrCam].FrzrCamModel == null) Utilities.Log_Debug("FrzrcamModel is null"); + if (ActFrzrCams[lastFrzrCam].FrzrCamTransform == null) Utilities.Log_Debug("FrzrcamTransform is null"); + Utilities.Log("Err: " + ex); + CameraManager.Instance.SetCameraFlight(); + } + } + + if (IVAKerbalName != null) ScreenMessages.RemoveMessage(IVAKerbalName); + if (IVAkerbalPart != null) ScreenMessages.RemoveMessage(IVAkerbalPart); + if (IVAkerbalPod != null) ScreenMessages.RemoveMessage(IVAkerbalPod); + if (Utilities.IsInInternal && ActFrzrCams.Count > 0) + { + // Set Top Left messages for FreezerCam mode + + // See if there is a kerbal seated/frozen in that seat get their reference + IVAkerbalPod = new ScreenMessage(Localizer.Format("autoLOC_DF_00071", ActFrzrCams[lastFrzrCam].FrzrCamSeatIndex), 1, ScreenMessageStyle.UPPER_LEFT); //autoLOC_DF_00071 = Pod:<<1>> + IVAkerbalPod.color = Color.white; + ScreenMessages.PostScreenMessage(IVAkerbalPod); + IVAkerbalPart = new ScreenMessage(ActFrzrCams[lastFrzrCam].FrzrCamPartName, 1, ScreenMessageStyle.UPPER_LEFT); + IVAkerbalPart.color = Color.white; + ScreenMessages.PostScreenMessage(IVAkerbalPart); + + string kerbalname; + try + { + if (ActFrzrCams[lastFrzrCam].FrzrCamPart.part.internalModel.seats[ActFrzrCams[lastFrzrCam].FrzrCamSeatIndex - 1].kerbalRef != null) + { + kerbalname = ActFrzrCams[lastFrzrCam].FrzrCamPart.part.internalModel.seats[ActFrzrCams[lastFrzrCam].FrzrCamSeatIndex - 1].kerbalRef.crewMemberName; + } + else + { + Utilities.Log_Debug("Kerbalref is null"); + kerbalname = string.Empty; + } + } + catch (Exception) + { + kerbalname = string.Empty; + } + IVAKerbalName = new ScreenMessage(kerbalname, 1, ScreenMessageStyle.UPPER_LEFT); + IVAKerbalName.color = Color.white; + ScreenMessages.PostScreenMessage(IVAKerbalName); + } + } + } + + private void FixedUpdate() + { + if (HighLogic.LoadedSceneIsEditor || Time.timeSinceLevelLoad < 5f || freezeThawActive) return; //Wait 5 seconds on level load before executing + currentTime = Planetarium.GetUniversalTime(); + //We only update every THREE seconds. + if (currentTime - lastFixedUpdateTime < 3f) + return; + + lastFixedUpdateTime = currentTime; + //Check if the active vessel has changed and if so, process. Should not happen as this is now called via GameEvent + if (HighLogic.LoadedSceneIsFlight) + { + if (FlightGlobals.ActiveVessel.id != ActVslID) + { + onVesselChange(FlightGlobals.ActiveVessel); + } + } + //We check/update kerbal Dictionary for comatose kerbals in EVERY Game Scene. + try + { + if (DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Count > 0) + { + CheckComaUpdate(); + } + } + catch (Exception ex) + { + Utilities.Log("FixedUpdate failed to update DeepFreeze Internal Comatose Kerbals Memory"); + Utilities.Log("Err: " + ex); + } + + //We check/update Vessel and Part Dictionary in EVERY Game Scene. + try + { + CheckVslUpdate(); + } + catch (Exception ex) + { + Utilities.Log("FixedUpdate failed to update DeepFreeze Internal Vessel Memory"); + Utilities.Log("Err: " + ex); + } + + //We check/update KAC alarms in EVERY Game Scene. + try + { + if (KACWrapper.AssemblyExists && KACWrapper.InstanceExists && KACWrapper.APIReady) + { + CheckKACAlarmsUpdate(); + } + } + catch (Exception ex) + { + Utilities.Log("FixedUpdate failed to update DeepFreeze Internal Alarm Memory"); + Utilities.Log("Err: " + ex); + } + } + #endregion + private void CheckComaUpdate() + { + // Check the knownfrozenkerbals for any tourists kerbals (IE: Comatose) if their time is up and reset them if it is. + ComakeysToDelete.Clear(); + //comaKerbals.Clear(); + foreach (var entry in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) + { + if (entry.Value.type == ProtoCrewMember.KerbalType.Tourist) + { + comaKerbals.Add(entry); + } + } + for (int i=0; i < comaKerbals.Count; i++) + { + if (Planetarium.GetUniversalTime() - comaKerbals[i].Value.lastUpdate > DeepFreeze.Instance.DFsettings.comatoseTime) // Is time up? + { + ProtoCrewMember crew = null; + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Tourist.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == comaKerbals[i].Key) + crew = enumerator.Current; + } + if (crew != null) + { + Vessel vsl = null; + List.Enumerator enumerator5 = FlightGlobals.Vessels.GetEnumerator(); + while (enumerator5.MoveNext()) + { + if (enumerator5.Current.id == comaKerbals[i].Value.vesselID) + vsl = enumerator5.Current; + } + if (vsl == null) + { + Utilities.Log("Failed to find Vessel for Comatose Kerbal - Critical error"); + return; + } + Part part = null; + List.Enumerator enumerator6 = vsl.parts.GetEnumerator(); + while (enumerator6.MoveNext()) + { + if (enumerator6.Current.flightID == comaKerbals[i].Value.partID) + part = enumerator6.Current; + } + if (part == null) + { + Utilities.Log("Failed to find Part for Comatose Kerbal - Critical error"); + return; + } + if (comaKerbals[i].Value.experienceTraitName == "Tourist") + { + DeepFreeze.Instance.setComatoseKerbal(part, crew, ProtoCrewMember.KerbalType.Tourist, false); + } + else + { + DeepFreeze.Instance.setComatoseKerbal(part, crew, ProtoCrewMember.KerbalType.Crew, false); + } + ComakeysToDelete.Add(comaKerbals[i].Key); + } + else + { + Utilities.Log("Unable to set comatose crew member " + comaKerbals[i].Key + " back to crew status."); + } + } + + } + for (int i = 0; i < ComakeysToDelete.Count; i++) + { + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(ComakeysToDelete[i]); + } + } + + private void ChkUnknownFrozenKerbals() + { + // Check the roster list for any unknown dead kerbals (IE: Frozen) that were not in the save file and add them. + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Unowned.GetEnumerator(); + int i = 0; + while (enumerator.MoveNext()) + { + if (enumerator.Current.rosterStatus == ProtoCrewMember.RosterStatus.Dead) + { + if (!DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.ContainsKey(enumerator.Current.name)) + { + // Update the saved frozen kerbals dictionary + KerbalInfo kerbalInfo = new KerbalInfo(Planetarium.GetUniversalTime()); + kerbalInfo.vesselID = Guid.Empty; + kerbalInfo.vesselName = ""; + kerbalInfo.type = enumerator.Current.type; + kerbalInfo.status = enumerator.Current.rosterStatus; + //kerbalInfo.seatName = "Unknown"; + kerbalInfo.seatIdx = 0; + kerbalInfo.partID = 0; + kerbalInfo.experienceTraitName = enumerator.Current.experienceTrait.Title; + try + { + Utilities.Log("Adding dead unknown kerbal " + enumerator.Current.name + + " AKA FROZEN kerbal to DeepFreeze List"); + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Add(enumerator.Current.name, + kerbalInfo); + } + catch (Exception ex) + { + Utilities.Log("Add of dead unknown kerbal " + enumerator.Current.name + " failed " + ex); + } + } + } + i++; + } + Utilities.Log("There are " + i + " unknownKerbals in the game roster."); + } + + internal void ChkActiveFrozenKerbals() + { + // Check the roster list for any crew kerbals that we think are frozen but aren't any more and delete them. + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Crew.GetEnumerator(); + int i = 0; + while (enumerator.MoveNext()) + { + if (DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.ContainsKey(enumerator.Current.name)) + { + // Remove the saved frozen kerbals dictionary + try + { + Utilities.Log_Debug("Removing crew kerbal " + enumerator.Current.name + " from DeepFreeze List"); + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(enumerator.Current.name); + } + catch (Exception ex) + { + Utilities.Log("Removal of crew kerbal " + enumerator.Current.name + " from frozen list failed " + ex); + } + } + + i++; + } + Utilities.Log("There are " + i + " crew Kerbals in the game roster."); + + } + + #region Events + private void ThawFreezeStart(Part part, string name) + { + freezeThawActive = true; + } + + private void ThawFreezeEnd(Part part, ProtoCrewMember crew) + { + freezeThawActive = false; + } + + private void ThawFreezeAbort(Part part, string name) + { + freezeThawActive = false; + } + + internal void onVesselRename(GameEvents.HostedFromToAction fromToAction) + { + //Update Vessel name for all frozen kerbals when a rename occurs + try + { + List frznKerbalkeys = new List(DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Keys); + foreach (string key in frznKerbalkeys) + { + if (DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals[key].vesselID == fromToAction.host.id) + { + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals[key].vesselName = fromToAction.to; + Utilities.Log_Debug("Updating Frozen Kerbal " + key + ",VesselName=" + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals[key].vesselName + ",VesselID=" + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals[key].vesselID); + } + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreezeGUI.Update failed to set vesselname for Frozen Kerbals"); + Utilities.Log("Err: " + ex); + } + + //Update Vessel names for all known vessels + try + { + List knownvslkeys = new List(DeepFreeze.Instance.DFgameSettings.knownVessels.Keys); + foreach (Guid key in knownvslkeys) + { + if (key == fromToAction.host.id) + { + DeepFreeze.Instance.DFgameSettings.knownVessels[key].vesselName = fromToAction.to; + Utilities.Log_Debug("Updating knownvessel " + key + ",VesselName=" + DeepFreeze.Instance.DFgameSettings.knownVessels[key].vesselName); + } + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreezeGUI.Update failed to set vesselname for Known vessel"); + Utilities.Log("Err: " + ex); + } + } + + internal void onVesselLoad(Vessel vessel) + { + if (HighLogic.LoadedSceneIsFlight) + { + Utilities.Log_Debug("OnVesselLoad activevessel " + FlightGlobals.ActiveVessel.id + " parametervesselid " + vessel.id); + resetFreezerCams(); + onVesselChange(vessel); + } + } + + internal void onVesselCreate(Vessel vessel) + { + if (HighLogic.LoadedSceneIsFlight) + { + if (FlightGlobals.ActiveVessel != null) + Utilities.Log_Debug("OnVesselCreate activevessel " + FlightGlobals.ActiveVessel.id); + Utilities.Log_Debug("OnVesselCreate parametervesselid " + vessel.id); + TmpDpFrzrActVsl = vessel.FindPartModulesImplementing(); + foreach (DeepFreezer frzr in TmpDpFrzrActVsl) + { + //Find the part in KnownFreezerParts and update the GUID + PartInfo partInfo; + if (DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(frzr.part.flightID, out partInfo)) + { + partInfo.vesselID = vessel.id; + } + //Iterate frozen kerbals in KnownFrozenKerbals and update the GUID + foreach (KeyValuePair frznKerbals in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) + { + if (frznKerbals.Value.partID == frzr.part.flightID) + { + frznKerbals.Value.vesselID = vessel.id; + frznKerbals.Value.vesselName = vessel.vesselName; + } + } + //Update the Frzr Parts internal frozenkerbals list GUID + foreach (FrznCrewMbr storedCrew in frzr.DFIStoredCrewList) + { + storedCrew.VesselID = vessel.id; + } + } + } + } + + internal void onPartCouple(GameEvents.FromToAction fromToAction) + { + if (HighLogic.LoadedSceneIsFlight) + { + Utilities.Log_Debug("OnPartCouple activevessel " + FlightGlobals.ActiveVessel.id + " fromPart " + fromToAction.from.flightID + "(" + fromToAction.from.vessel.id + ") toPart " + fromToAction.to.flightID + "(" + fromToAction.to.vessel.id + ")"); + List TmpDpFrzrActVsl = fromToAction.from.vessel.FindPartModulesImplementing(); + foreach (DeepFreezer frzr in TmpDpFrzrActVsl) + { + //Find the part in KnownFreezerParts and update the GUID + PartInfo partInfo; + if (DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(frzr.part.flightID, out partInfo)) + { + partInfo.vesselID = fromToAction.to.vessel.id; + } + //Iterate frozen kerbals in KnownFrozenKerbals and update the GUID + foreach (KeyValuePair frznKerbals in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) + { + if (frznKerbals.Value.partID == frzr.part.flightID) + { + frznKerbals.Value.vesselID = fromToAction.to.vessel.id; + frznKerbals.Value.vesselName = fromToAction.to.vessel.vesselName; + } + } + //Update the Frzr Parts internal frozenkerbals list GUID + foreach (FrznCrewMbr storedCrew in frzr.DFIStoredCrewList) + { + storedCrew.VesselID = fromToAction.to.vessel.id; + } + } + //Now resetFrozenKerbals in the parts + foreach (DeepFreezer frzr in TmpDpFrzrActVsl) + { + frzr.resetFrozenKerbals(); + } + //refreshPortraits = true; + //refreshPortraitsTimer = Planetarium.GetUniversalTime(); + } + } + + internal void onVesselChange(Vessel vessel) + { + if (HighLogic.LoadedSceneIsFlight) + { + Utilities.Log_Debug("OnVesselChange activevessel " + FlightGlobals.ActiveVessel.name + "(" + FlightGlobals.ActiveVessel.id + ") parametervessel " + vessel.name + "(" + vessel.id + ")"); + //chk if current active vessel Has one or more DeepFreezer modules attached + try + { + DpFrzrActVsl = FlightGlobals.ActiveVessel.FindPartModulesImplementing(); + if (DpFrzrActVsl.Count == 0) + { + ActVslHasDpFrezr = false; + } + else + { + ActVslHasDpFrezr = true; + DpFrzrActVsl = vessel.FindPartModulesImplementing(); + //Check if vessel id has changed or last freezer cam transforms is now null, reset the freezer cams. + if (ActVslID != vessel.id || ActFrzrCams.Count > 0) + { + foreach (DeepFreezer frzr in DpFrzrActVsl) + { + if (frzr.partHasInternals) + { + resetFreezerCams(); + break; + } + } + } + } + ActVslID = FlightGlobals.ActiveVessel.id; + Utilities.Log_Debug("OnVesselChange ActVslID " + ActVslID + " HasFreezers " + ActVslHasDpFrezr + " FreezerCams Listed " + ActFrzrCams.Count); + } + catch (Exception ex) + { + Utilities.Log("Failed to set active vessel and Check Freezers"); + Utilities.Log("Err: " + ex); + //ActVslHasDpFrezr = false; + } + } + else + { + ActVslHasDpFrezr = false; + } + } + + #endregion + internal void AddTests() + { + Utilities.Log_Debug("Adding DF Engineer Test"); + IDesignConcern DFtest = new DFEngReport(); + EngineersReport.Instance.AddTest(DFtest); + } + + private void resetFreezerCams() + { + try + { + ActFrzrCams.Clear(); + lastFrzrCam = 0; + Utilities.Log_Debug("ActVslHasDpFrezer " + ActVslHasDpFrezr + " #ofFrzrs " + DpFrzrActVsl.Count); + foreach (DeepFreezer Frzr in DpFrzrActVsl) + { + if (Frzr.part.internalModel != null) + { + for (int i = 0; i < Frzr.FreezerSize; i++) + { + string frzrcamname = "FrzCam" + (i + 1); + Transform frzrcam = Frzr.part.internalModel.FindModelComponent(frzrcamname); + if (frzrcam != null) + { + VslFrzrCams vslfrzrcam = new VslFrzrCams(frzrcam, Frzr.part.internalModel, i + 1, Frzr.part.name.Substring(8, 1) == "R" ? Frzr.part.name.Substring(0, 9) : Frzr.part.name.Substring(0, 8), Frzr); + ActFrzrCams.Add(vslfrzrcam); + Utilities.Log_Debug("Adding ActFrzrCams " + vslfrzrcam.FrzrCamModel.internalName + " " + vslfrzrcam.FrzrCamTransform.name); + } + else + { + Utilities.Log_Debug("Unable to find FrzCam transform " + frzrcamname); + } + } + } + else + { + Utilities.Log_Debug("Frzr " + Frzr.name + " internalmodel is null"); + } + } + } + catch (Exception) + { + Utilities.Log("Failed to resetFreezerCams"); + // Utilities.Log("Err: " + ex); + } + } + + #region UpdateVesselDictionary + + private void CheckVslUpdate() + { + // Called every fixed update from fixedupdate - Check for vessels that have been deleted and remove from Dictionary + // also updates current active vessel details/settings + // adds new vessel if current active vessel is not known and updates it's details/settings + //double currentTime = Planetarium.GetUniversalTime(); + //allVessels.Clear(); + vesselsToDelete.Clear(); + partsToDelete.Clear(); + //knownVessels.Clear(); + allVessels = FlightGlobals.Vessels; + knownVessels = DeepFreeze.Instance.DFgameSettings.knownVessels; + Utilities.Log_Debug("CheckVslUpdate start"); + //* Update known vessels. + foreach (var entry in knownVessels) + { + if (AllVslsErrorCount > 0 && AllVslsErrorCount < 5) + { + Utilities.Log("knownvessels id = " + entry.Key + " Name = " + entry.Value.vesselName); + } + Utilities.Log_Debug("knownvessels id = " + entry.Key + " Name = " + entry.Value.vesselName); + vesselId = entry.Key; + VesselInfo vesselInfo = entry.Value; + vessel = null; + try + { + if (AllVslsErrorCount < 5) + { + List.Enumerator enumerator = allVessels.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.id == vesselId) + { + vessel = enumerator.Current; + break; + } + } + enumerator.Dispose(); + } + else + continue; + } + catch (Exception ex) + { + AllVslsErrorCount++; + DeepFreeze.Instance.DFgameSettings.DmpKnownVessels(); + if (allVessels == null) + { + Utilities.Log("FlightGlobals.Vessels = NULL but never should be"); + } + else + { + if (allVessels.Count == 0) + { + Utilities.Log("FlightGlobals.Vessels.Count = 0"); + } + else + { + foreach (Vessel vsl in allVessels) + { + Utilities.Log("Vessel " + vsl.id + " name = " + vsl.name); + } + } + } + Utilities.Log("Exception: " + ex); + if (entry.Value.numFrznCrew == 0) + { + Utilities.Log("Removing entry as vessel has no frozen crew"); + vesselsToDelete.Add(vesselId); + foreach (var frzrpart in DeepFreeze.Instance.DFgameSettings.knownFreezerParts) + { + if (frzrpart.Value.vesselID == vesselId) + { + partsToDelete.Add(frzrpart.Key); + } + } + continue; + } + } + if (vessel == null) + { + Utilities.Log_Debug("Deleting vessel " + vesselInfo.vesselName + " - vessel does not exist anymore"); + vesselsToDelete.Add(vesselId); + foreach (var frzrpart in DeepFreeze.Instance.DFgameSettings.knownFreezerParts) + { + if (frzrpart.Value.vesselID == vesselId) + { + partsToDelete.Add(frzrpart.Key); + } + } + continue; + } + if (vessel.loaded) + { + UpdateVesselInfo(vesselInfo, vessel, currentTime); + crewCapacity = UpdateVesselCounts(vesselInfo, vessel, currentTime); + if (vessel.FindPartModulesImplementing().Count == 0) + { + Utilities.Log_Debug("Deleting vessel " + vesselInfo.vesselName + " - no freezer parts anymore"); + vesselsToDelete.Add(vesselId); + foreach (var frzrpart in DeepFreeze.Instance.DFgameSettings.knownFreezerParts) + { + if (frzrpart.Value.vesselID == vesselId) + { + partsToDelete.Add(frzrpart.Key); + } + } + } + else + { + if (DeepFreeze.Instance.DFsettings.ECreqdForFreezer && vesselInfo.numFrznCrew > 0) + { + UpdatePredictedVesselEC(vesselInfo, vessel, currentTime); + } + if (vesselInfo.hasextDoor || vesselInfo.hasextPod) + { + // If vessel is Not ActiveVessel and has a Transparent Pod reset the Cryopods. + if (FlightGlobals.ActiveVessel != vessel) + { + DpFrzrLoadedVsl.Clear(); + DpFrzrLoadedVsl = vessel.FindPartModulesImplementing(); + foreach (DeepFreezer frzr in DpFrzrLoadedVsl) + { + if (frzr.ExternalDoorActive || frzr.isPodExternal) + { + Utilities.Log_Debug("chkvslupdate loaded freezer with door or external pod, reset the cryopods"); + frzr.resetCryopods(false); + } + } + } + } + } + } + else //vessel not loaded + { + if ((DFInstalledMods.IsBGRInstalled || !Utilities.timewarpIsValid(5)) && DeepFreeze.Instance.DFsettings.backgroundresources) + { + if (UnloadedResources.Instance != null) + { + UnloadedResources.Instance.AddInterestedVessel(vessel.protoVessel); + } + } + UpdatePredictedVesselEC(vesselInfo, vessel, currentTime); + vesselInfo.hibernating = true; + } + } + + // Delete vessels we don't care about any more. + for (int i = 0; i < vesselsToDelete.Count; ++i) + { + if (DFInstalledMods.IsBGRInstalled && DeepFreeze.Instance.DFsettings.backgroundresources) + { + if (UnloadedResources.Instance != null) + { + UnloadedResources.Instance.RemoveInterestedVessel(vesselsToDelete[i]); + } + } + DeepFreeze.Instance.DFgameSettings.knownVessels.Remove(vesselsToDelete[i]); + } + // Delete parts that were part of those vessels. + for (int i = 0; i < partsToDelete.Count; ++i) + { + DeepFreeze.Instance.DFgameSettings.knownFreezerParts.Remove(partsToDelete[i]); + } + + // Scan through all in-game vessels and add any new ones we don't know about that have a freezer module. + foreach (Vessel vessel in FlightGlobals.VesselsLoaded) + { + if (!knownVessels.ContainsKey(vessel.id) && vessel.FindPartModulesImplementing().Count > 0) + { + Utilities.Log("New vessel: " + vessel.vesselName + " (" + vessel.id + ")"); + vesselInfo.vesselName = vessel.vesselName; + UpdateVesselInfo(vesselInfo, vessel, currentTime); + crewCapacity = UpdateVesselCounts(vesselInfo, vessel, currentTime); + knownVessels[vessel.id] = vesselInfo; + } + } + Utilities.Log_Debug("CheckVslUpdate complete"); + } + + private void UpdatePredictedVesselEC(VesselInfo vesselInfo, Vessel vessel, double currentTime) + { + double ECreqdsincelastupdate = 0f; + int frznChargeRequired = 0; + List> DpFrzrVsl = new List>(); + foreach (var frzrpart in DeepFreeze.Instance.DFgameSettings.knownFreezerParts) + { + if (frzrpart.Value.vesselID == vessel.id) + DpFrzrVsl.Add(frzrpart); + } + for (int i = 0; i < DpFrzrVsl.Count; i++) + { + //calculate the predicated time EC will run out + double timeperiod = Planetarium.GetUniversalTime() - DpFrzrVsl[i].Value.timeLastElectricity; + frznChargeRequired = (int)DpFrzrVsl[i].Value.frznChargeRequired; + ECreqdsincelastupdate += frznChargeRequired / 60.0f * timeperiod * DpFrzrVsl[i].Value.numFrznCrew; + DpFrzrVsl[i].Value.deathCounter = currentTime; + // Utilities.Log_Debug("predicted EC part " + frzr.Value.vesselID + " " + frzr.Value.PartName + " FrznChargeRequired " + frznChargeRequired + " timeperiod " + timeperiod + " #frzncrew " + frzr.Value.numFrznCrew); + } + double ECafterlastupdate = vesselInfo.storedEC - ECreqdsincelastupdate; + double predictedMinutes = ECafterlastupdate / frznChargeRequired; // This probably should be per PART, but for simplicity we will do for the whole vessel + vesselInfo.predictedECOut = predictedMinutes * 60; + // Utilities.Log_Debug("UpdatePredictedVesselEC vessel " + vessel.id + " " + vessel.name + " StoredEC=" + vesselInfo.storedEC + " ECreqd=" + ECreqdsincelastupdate + " Prediction Secs=" + vesselInfo.predictedECOut); + // Utilities.Log_Debug("ECafterlastupdate " + ECafterlastupdate + " FrznChargeRequired " + frznChargeRequired + " predictedMinutes " + predictedMinutes); + } + + private void UpdateVesselInfo(VesselInfo vesselInfo, Vessel vessel, double currentTime) + { + // Utilities.Log_Debug("UpdateVesselInfo " + vesselInfo.vesselName); + vesselInfo.vesselType = vessel.vesselType; + vesselInfo.lastUpdate = Planetarium.GetUniversalTime(); + vesselInfo.hibernating = false; + vesselInfo.hasextDoor = false; + vesselInfo.hasextPod = false; + DpFrzrLoadedVsl.Clear(); + DpFrzrLoadedVsl = vessel.FindPartModulesImplementing(); + for (int i = 0; i < DpFrzrLoadedVsl.Count; i++) + //foreach (DeepFreezer frzr in DpFrzrLoadedVsl) + { + // do we have a known part? If not add it + if (!DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(DpFrzrLoadedVsl[i].part.flightID, out partInfo)) + { + Utilities.Log("New Freezer Part: " + DpFrzrLoadedVsl[i].name + "(" + DpFrzrLoadedVsl[i].part.flightID + ")" + " (" + vessel.id + ")"); + partInfo = new PartInfo(vessel.id, DpFrzrLoadedVsl[i].name, currentTime); + //partInfo.vesselID = vessel.id; + //partInfo.PartName = frzr.name; + partInfo.hibernating = false; + partInfo.ECWarning = false; + partInfo.TempWarning = false; + partInfo.lastUpdate = currentTime; + partInfo.crewMembers.Clear(); + partInfo.crewMemberTraits.Clear(); + + + partInfo.hasextDoor = DpFrzrLoadedVsl[i].ExternalDoorActive; + partInfo.hasextPod = DpFrzrLoadedVsl[i].isPodExternal; + partInfo.numSeats = DpFrzrLoadedVsl[i].FreezerSize; + partInfo.timeLastElectricity = DpFrzrLoadedVsl[i].timeSinceLastECtaken; + partInfo.frznChargeRequired = DpFrzrLoadedVsl[i].FrznChargeRequired; + partInfo.timeLastTempCheck = DpFrzrLoadedVsl[i].timeSinceLastTmpChk; + partInfo.deathCounter = DpFrzrLoadedVsl[i].deathCounter; + partInfo.tmpdeathCounter = DpFrzrLoadedVsl[i].tmpdeathCounter; + partInfo.outofEC = DpFrzrLoadedVsl[i].DFFreezerOutofEC; + partInfo.TmpStatus = DpFrzrLoadedVsl[i].DFFrzrTmp; + partInfo.cabinTemp = DpFrzrLoadedVsl[i].CabinTemp; + for (int j = 0; j < DpFrzrLoadedVsl[i].part.protoModuleCrew.Count; j++) + { + partInfo.crewMembers.Add(DpFrzrLoadedVsl[i].part.protoModuleCrew[j].name); + partInfo.crewMemberTraits.Add(DpFrzrLoadedVsl[i].part.protoModuleCrew[j].experienceTrait.Title); + } + + DeepFreeze.Instance.DFgameSettings.knownFreezerParts[DpFrzrLoadedVsl[i].part.flightID] = partInfo; + } + else // Update existing entry + { + partInfo.hasextDoor = DpFrzrLoadedVsl[i].ExternalDoorActive; + partInfo.hasextPod = DpFrzrLoadedVsl[i].isPodExternal; + partInfo.numSeats = DpFrzrLoadedVsl[i].FreezerSize; + partInfo.timeLastElectricity = DpFrzrLoadedVsl[i].timeSinceLastECtaken; + partInfo.frznChargeRequired = DpFrzrLoadedVsl[i].FrznChargeRequired; + partInfo.timeLastTempCheck = DpFrzrLoadedVsl[i].timeSinceLastTmpChk; + partInfo.deathCounter = DpFrzrLoadedVsl[i].deathCounter; + partInfo.tmpdeathCounter = DpFrzrLoadedVsl[i].tmpdeathCounter; + partInfo.outofEC = DpFrzrLoadedVsl[i].DFFreezerOutofEC; + partInfo.TmpStatus = DpFrzrLoadedVsl[i].DFFrzrTmp; + partInfo.cabinTemp = DpFrzrLoadedVsl[i].CabinTemp; + partInfo.crewMembers.Clear(); + partInfo.crewMemberTraits.Clear(); + for (int j = 0; j < DpFrzrLoadedVsl[i].part.protoModuleCrew.Count; j++) + { + partInfo.crewMembers.Add(DpFrzrLoadedVsl[i].part.protoModuleCrew[j].name); + partInfo.crewMemberTraits.Add(DpFrzrLoadedVsl[i].part.protoModuleCrew[j].experienceTrait.Title); + } + } + //now update the knownfreezerpart and any related vesselinfo field + if (DpFrzrLoadedVsl[i].ExternalDoorActive) + vesselInfo.hasextDoor = true; + if (DpFrzrLoadedVsl[i].isPodExternal) + vesselInfo.hasextPod = true; + } + } + + private int UpdateVesselCounts(VesselInfo vesselInfo, Vessel vessel, double currentTime) + { + // save current toggles to current vesselinfo + // Utilities.Log_Debug("UpdateVesselCounts " + vessel.id); + crewCapacity = 0; + vesselInfo.ClearAmounts(); // numCrew = 0; numOccupiedParts = 0; numseats = 0; + for (int i = 0; i < vessel.parts.Count; i++) + //foreach (Part part in vessel.parts) + { + DeepFreezer freezer = vessel.parts[i].FindModuleImplementing(); + if (freezer != null) // this vessel part does contain a freezer + { + Utilities.Log_Debug("part:" + vessel.parts[i].name + " Has Freezer"); + //first Update the PartInfo counts + + if (DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(freezer.part.flightID, out partInfo)) + { + partInfo.numCrew = freezer.part.protoModuleCrew.Count; + partInfo.numFrznCrew = freezer.DFIStoredCrewList.Count; + } + //Now update the VesselInfo counts + crewCapacity += freezer.FreezerSize; + vesselInfo.numSeats += freezer.FreezerSize; + vesselInfo.numCrew += vessel.parts[i].protoModuleCrew.Count; + vesselInfo.numFrznCrew += freezer.DFIStoredCrewList.Count; + // Utilities.Log_Debug("numcrew:" + part.protoModuleCrew.Count + " numfrzncrew:" + freezer.DFIStoredCrewList.Count()); + if (vessel.parts[i].protoModuleCrew.Count > 0 || freezer.DFIStoredCrewList.Count > 0) + { + ++vesselInfo.numOccupiedParts; + } + } + else //this vessel part does not contain a freezer + { + crewCapacity += vessel.parts[i].CrewCapacity; + vesselInfo.numSeats += vessel.parts[i].CrewCapacity; + if (vessel.parts[i].protoModuleCrew.Count > 0) + { + vesselInfo.numCrew += vessel.parts[i].protoModuleCrew.Count; + ++vesselInfo.numOccupiedParts; + } + if (vessel.parts[i].Resources.Contains("ElectricCharge")) + { + vesselInfo.storedEC += vessel.parts[i].Resources.Get("ElectricCharge").amount; + } + } + } + // Utilities.Log_Debug("UpdateVesselCounts " + vessel.id + " complete. numCrew=" + vesselInfo.numCrew + " numfrzncrew=" + vesselInfo.numFrznCrew + " crewcapacity=" + crewCapacity + " numoccupparts=" + vesselInfo.numOccupiedParts); + return crewCapacity; + } + + private bool vslHasFreezer(Guid vesselID) + { + if (DeepFreeze.Instance.DFgameSettings.knownVessels.ContainsKey(vesselID)) + { + return true; + } + return false; + } + + #endregion UpdateVesselDictionary + + #region KACAlarms + + private void KAC_onAlarmStateChanged(KACWrapper.KACAPI.AlarmStateChangedEventArgs e) + { + //This is triggered whenever the KAC API triggers an Alarm event. + //So we have to check it is an alarm we are interested in and we are only interested in the Triggered EventType. + Utilities.Log_Debug("KAC Alarm triggered " + e.alarm.Name + "->" + e.eventType); + /* EventType = Created,Triggered,Closed,Deleted */ + if (e.eventType == KACWrapper.KACAPI.KACAlarm.AlarmStateEventsEnum.Triggered) + { + //Is it an alarm we are tracking? If so, break it down. + if (DeepFreeze.Instance.DFgameSettings.knownKACAlarms.ContainsKey(e.alarm.ID)) + { + Utilities.Log_Debug("Alarm is known so set Execute to true"); + DeepFreeze.Instance.DFgameSettings.knownKACAlarms[e.alarm.ID].AlarmExecute = true; + // Do some messages if the LoadedScene is not flight or the active vessel is not the one we just got the alarm for. + //The user has to manually switch to that vessel. Maybe we can automate this in a later version. + if (!HighLogic.LoadedSceneIsFlight) + { + SwitchVslAlarmMsg(DeepFreeze.Instance.DFgameSettings.knownKACAlarms[e.alarm.ID].Name); + } + else + { + if (FlightGlobals.ActiveVessel.id != DeepFreeze.Instance.DFgameSettings.knownKACAlarms[e.alarm.ID].VesselID) + { + SwitchVslAlarmMsg(DeepFreeze.Instance.DFgameSettings.knownKACAlarms[e.alarm.ID].Name); + } + } + } + } + } + + private void SwitchVslAlarmMsg(string vesselname) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00109", vesselname), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00109 = A DeepFreeze Alarm event has occurred. Please Switch to <<1>> to execute. + } + + private void CheckKACAlarmsUpdate() + { + var alarmstoDelete = new List(); + //iterate all the alarms looking for vessel.ID matches + foreach (var entry in DeepFreeze.Instance.DFgameSettings.knownKACAlarms) + { + Utilities.Log_Debug("knownKACAlarms id = " + entry.Key + " Name = " + entry.Value.Name); + KACWrapper.KACAPI.KACAlarm alarm = null; + List.Enumerator enumerator = KACWrapper.KAC.Alarms.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.ID == entry.Key) + alarm = enumerator.Current; + } + if (alarm == null && entry.Value.AlarmExecute == false) //Alarm not known to KAC any more and not still executing so delete it. + { + Utilities.Log_Debug("Alarm not known to KAC any more so deleting"); + alarmstoDelete.Add(entry.Key); + continue; + } + // Check if Alarm has been modified and no longer has any DeepFreeze association, in which case we delete it. + if ((entry.Value.FrzKerbals.Count == 0 && entry.Value.ThwKerbals.Count == 0) || !DeepFreeze.Instance.DFgameSettings.knownVessels.ContainsKey(entry.Value.VesselID)) + // No FREEZE or THAW events in the Notes and unknown vessel, so delete it. + { + Utilities.Log_Debug("Alarm has no THAW FREEZE any more so deleting"); + alarmstoDelete.Add(entry.Key); + continue; + } + // Check if alarm has occurred and still executing and try to execute it. + if (entry.Value.AlarmExecute) + { + if (entry.Value.ThwKerbals.Count == 0 && entry.Value.FrzKerbals.Count == 0) + { + // we are all done. Delete the alarm. Do a message. + Utilities.Log_Debug("Execution of alarm for vessel " + entry.Value.Name + " is complete"); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00110"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00110 = DeepFreeze Alarm processing completed. + alarmstoDelete.Add(entry.Key); + continue; + } + if (!DeepFreeze.Instance.DFgameSettings.knownVessels.ContainsKey(entry.Value.VesselID)) // vessel doesn't exist any more, so just delete the executing alarm. + { + Utilities.Log_Debug("Executing alarm for vessel " + entry.Value.Name + " deleted as vessel no longer exists"); + alarmstoDelete.Add(entry.Key); + continue; + } + if (!HighLogic.LoadedSceneIsFlight) //If we aren't in flightmode we can't, so just do message and skip this logic section + { + Utilities.Log_Debug("Executing alarm for vessel " + entry.Value.Name + " scene is not flight"); + SwitchVslAlarmMsg(DeepFreeze.Instance.DFgameSettings.knownKACAlarms[entry.Key].Name); + continue; + } + if (FlightGlobals.ActiveVessel.id != DeepFreeze.Instance.DFgameSettings.knownKACAlarms[entry.Key].VesselID) // We are in flight, but active vessel is not the one we want + { + Utilities.Log_Debug("Executing alarm for vessel " + entry.Value.Name + " not the active vessel"); + SwitchVslAlarmMsg(DeepFreeze.Instance.DFgameSettings.knownKACAlarms[entry.Key].Name); + continue; + } + // Ok , all that is out of the way, so no we really try to execute it. + //THAW first + Utilities.Log_Debug("Alarm is executing"); + if (entry.Value.ThwKerbals.Count > 0) + { + foreach (string kerbnme in entry.Value.ThwKerbals) + { + Utilities.Log_Debug("Dump ThwKerbals list entry=" + kerbnme); + } + // First we find the ThwKerbal part and if they are still on-board frozen. + // Then check the part isn't busy already and start the thaw process. + bool Found = false; + string thwkerbalname = entry.Value.ThwKerbals[0]; + Utilities.Log_Debug("Executing alarm for vessel " + entry.Value.Name + " looking to thaw crewmember " + thwkerbalname + " finding the part"); + foreach (DeepFreezer frzr in DpFrzrActVsl) + { + // Check if they are in the frozen list for this part or not? + FrznCrewMbr tmpcrew = null; + List.Enumerator enumerator2 = frzr.DFIStoredCrewList.GetEnumerator(); + while (enumerator2.MoveNext()) + { + if (enumerator2.Current.CrewName == thwkerbalname) + tmpcrew = enumerator2.Current; + } + if (tmpcrew != null) + { + //They are in this part. + Found = true; + if (frzr.DFIcrewXferFROMActive || frzr.DFIcrewXferTOActive || frzr.DFIIsFreezeActive || frzr.DFIIsThawActive) + { + //part is busy, so we wait. + Utilities.Log_Debug("We found the crewmember and the part, but it is busy, so we wait"); + break; + } + //If we just switched to the vessel we have to wait for the vessel to load. + if (Time.timeSinceLevelLoad < 6f) + { + Utilities.Log_Debug("We found the crewmember and the part, but < 4 secs since level loaded, so we wait"); + break; + } + //If we get here, we have found the kerbal, and the part, and it isn't busy. So we THAW!!!!!! + Utilities.Log_Debug("We found the crewmember and the part and it isn't busy, so we THAW!!!"); + frzr.beginThawKerbal(thwkerbalname); + entry.Value.ThwKerbals.Remove(thwkerbalname); + foreach (string kerbnme in entry.Value.ThwKerbals) + { + Utilities.Log_Debug("Dump ThwKerbals list entry=" + kerbnme); + } + ModifyKACAlarm(alarm, entry.Value.FrzKerbals, entry.Value.ThwKerbals); + break; + } + } + if (!Found) + { + //We didn't find them anywhere. Remove the thaw request. + entry.Value.ThwKerbals.Remove(thwkerbalname); + Utilities.Log_Debug("We didn't find the thaw kerbal " + thwkerbalname + " anywhere on the vessel so we deleted the request"); + } + } + else + { + if (entry.Value.FrzKerbals.Count > 0) + { + foreach (string kerbnme in entry.Value.FrzKerbals) + { + Utilities.Log_Debug("Dump FrzKerbals list entry=" + kerbnme); + } + // First we find the FrzKerbal part and if they are still on-board + // Then check the part isn't busy already and start the freeze process. + bool Found = false; + List vslcrew = FlightGlobals.ActiveVessel.GetVesselCrew(); + string frzkerbalname = entry.Value.FrzKerbals[0]; + ProtoCrewMember crewmember = null; + List.Enumerator enumerator3 = vslcrew.GetEnumerator(); + while (enumerator3.MoveNext()) + { + if (enumerator3.Current.name == frzkerbalname) + crewmember = enumerator3.Current; + } + if (crewmember == null) + { + //They aren't in the vessel any more. So delete this thaw and move on. + Utilities.Log_Debug("Executing alarm for vessel " + entry.Value.Name + " looking to freeze crewmember " + frzkerbalname + " but the aren't on-board so move on"); + entry.Value.FrzKerbals.Remove(frzkerbalname); + continue; + } + //ProtoCrewMember crewmember = FlightGlobals.ActiveVessel.GetVesselCrew().Find(a => a.name == entry.Value.ThwKerbals[0]); + Utilities.Log_Debug("Executing alarm for vessel " + entry.Value.Name + " looking to freeze crewmember " + frzkerbalname + " finding the part"); + foreach (DeepFreezer frzr in DpFrzrActVsl) + { + if (frzr.part.protoModuleCrew.Contains(crewmember)) + { + //They are in this part. + Found = true; + if (frzr.DFIcrewXferFROMActive || frzr.DFIcrewXferTOActive || frzr.DFIIsFreezeActive || frzr.DFIIsThawActive) + { + //part is busy, so we wait. + Utilities.Log_Debug("We found the crewmember and the part, but it is busy, so we wait"); + break; + } + //If we just switched to the vessel we have to wait for the vessel to load. + if (Time.timeSinceLevelLoad < 6f) + { + Utilities.Log_Debug("We found the crewmember and the part, but < 4 secs since level loaded, so we wait"); + break; + } + //If we get here, we have found the kerbal, and the part, and it isn't busy. So we FREEZE!!!!!! + Utilities.Log_Debug("We found the crewmember and the part and it isn't busy, so we FREEZE!!!"); + frzr.beginFreezeKerbal(crewmember); + entry.Value.FrzKerbals.Remove(frzkerbalname); + foreach (string kerbnme in entry.Value.FrzKerbals) + { + Utilities.Log_Debug("Dump FrzKerbals list entry=" + kerbnme); + } + ModifyKACAlarm(alarm, entry.Value.FrzKerbals, entry.Value.ThwKerbals); + break; + } + } + if (!Found) + { + //We didn't find them anywhere. Remove the freeze request. + entry.Value.FrzKerbals.Remove(frzkerbalname); + Utilities.Log_Debug("We didn't find the freeze kerbal " + frzkerbalname + " anywhere on the vessel so we deleted the request"); + } + } + } + } + } + + alarmstoDelete.ForEach(id => DeepFreeze.Instance.DFgameSettings.knownKACAlarms.Remove(id)); + + //loop through all the KAC alarms. If the alarm is NOT already in the KnownList and the Vessel has a Freezer association that we know of, we add it to the KnownList + foreach (var entry in KACWrapper.KAC.Alarms) + { + if (!DeepFreeze.Instance.DFgameSettings.knownKACAlarms.ContainsKey(entry.ID)) // So we don't already know about it + { + if (entry.VesselID != string.Empty && entry.AlarmType != KACWrapper.KACAPI.AlarmTypeEnum.Crew) + { + Guid tmpid = Guid.Empty; + try + { + tmpid = new Guid(entry.VesselID); + } + catch (FormatException) + { + if (invalidKACGUIDItems < 10) + { + Debug.Log("DeepFreeze invalid KAC alarm GUID caught (" + entry.VesselID + ")"); + invalidKACGUIDItems++; + } + } + if (tmpid != Guid.Empty) + { + if (DeepFreeze.Instance.DFgameSettings.knownVessels.ContainsKey(tmpid)) // So we do know that vessel does have a Freezer Assocation so we add it to the KnownList + { + AlarmInfo tempAlarmInfo = new AlarmInfo(entry.Name, tmpid); + UpdateKACAlarmInfo(tempAlarmInfo, entry); + DeepFreeze.Instance.DFgameSettings.knownKACAlarms.Add(entry.ID, tempAlarmInfo); + } + } + } + } + else //We do know about it, we update it's details + { + Guid tmpid = Guid.Empty; + try + { + tmpid = new Guid(entry.VesselID); + } + catch (FormatException) + { + if (invalidKACGUIDItems < 10) + { + Debug.Log("DeepFreeze invalid KAC alarm GUID caught (" + entry.VesselID + ")"); + invalidKACGUIDItems++; + } + } + if (tmpid != Guid.Empty) + { + AlarmInfo tempAlarmInfo = new AlarmInfo(entry.Name, tmpid); + UpdateKACAlarmInfo(tempAlarmInfo, entry); + tempAlarmInfo.AlarmExecute = DeepFreeze.Instance.DFgameSettings.knownKACAlarms[entry.ID].AlarmExecute; + DeepFreeze.Instance.DFgameSettings.knownKACAlarms[entry.ID] = tempAlarmInfo; + } + } + } + } + + private void UpdateKACAlarmInfo(AlarmInfo alarmInfo, KACWrapper.KACAPI.KACAlarm alarm) + { + alarmInfo.AlarmType = alarm.AlarmType; + alarmInfo.AlarmTime = alarm.AlarmTime; + alarmInfo.AlarmMargin = alarm.AlarmMargin; + alarmInfo.Notes = alarm.Notes; + string tmpnotes = ParseKACNotes(alarm.Notes, out alarmInfo.FrzKerbals, out alarmInfo.ThwKerbals); + } + + internal void ModifyKACAlarm(KACWrapper.KACAPI.KACAlarm alarm, List InFrzKbls, List InThwKbls) + { + // First we strip out any existing DeepFreeze Events from the notes. + List _FrzKbls; + List _ThwKbls; + string notes = ParseKACNotes(alarm.Notes, out _FrzKbls, out _ThwKbls); + //Now we add our new DeepFreeze Events back in. + string newnotes = CreateKACNotes(notes, InFrzKbls, InThwKbls); + Utilities.Log_Debug("ModifyKACAlarm oldnotes= \r\n" + alarm.Notes); + Utilities.Log_Debug("Stripped out notes= \r\n" + notes); + Utilities.Log_Debug("NewNotes= \r\n" + newnotes); + alarm.Notes = newnotes; + } + + internal string ParseKACNotes(string Notes, out List InFrzKbls, out List InThwKbls) + { + // Parse out the KAC Alarm Notes. Input is Existing Alarm Notes. Outputs are notes with DeepFreeze events stripped out and a list of Kerbals to Freeze and list of Kerbals to Thaw + List _frzKbls = new List(); + List _thwKbls = new List(); + string NewNotes = string.Empty; + string[] noteStrings = Notes.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + if (noteStrings.Length > 0) + { + for (int i = 0; i < noteStrings.Length; i++) + { + // Utilities.Log_Debug("ParseKACNotes Line=" + noteStrings[i]); + string[] notelinewords = noteStrings[i].Split(' '); + if (notelinewords.Length > 2) + { + if (notelinewords[0] == "THAW") + { + string thwkrblname = notelinewords[1] + " " + notelinewords[2]; + _thwKbls.Add(thwkrblname); + } + else + { + if (notelinewords[0] == "FREEZE") + { + string frzkrblname = notelinewords[1] + " " + notelinewords[2]; + _frzKbls.Add(frzkrblname); + } + else + { + NewNotes += noteStrings[i] + "\r\n"; + } + } + } + else + { + NewNotes += noteStrings[i] + "\r\n"; + } + } + } + InFrzKbls = _frzKbls; + InThwKbls = _thwKbls; + return NewNotes; + } + + private string CreateKACNotes(string Notes, List InFrzKbls, List InThwKbls) + { + // Creates new KAC alarm Notes. Inputs are existing Notes (with any previous DeepFreeze events stripped out), List of Kerbals to Freeze and List of Kerbals to Thaw. + string NewNotes = string.Empty; + NewNotes += Notes + "\r\n"; + foreach (string kerbal in InFrzKbls) + { + NewNotes += "FREEZE " + kerbal + "\r\n"; + } + foreach (string kerbal in InThwKbls) + { + NewNotes += "THAW " + kerbal + "\r\n"; + } + return NewNotes; + } + + #endregion KACAlarms + } +} \ No newline at end of file diff --git a/Source/DFPartEvents.cs b/Source/DFPartEvents.cs new file mode 100644 index 0000000..2dbec0d --- /dev/null +++ b/Source/DFPartEvents.cs @@ -0,0 +1,383 @@ +using System.Collections.Generic; +using KSP.Localization; +using RSTUtils; + + +namespace DF +{ + public class CryopodEvents + { + public class EventData + { + public string kerbalName; + public BaseEvent eventItem; + + public EventData(string kerbalName, BaseEvent eventItem) + { + this.kerbalName = kerbalName; + this.eventItem = eventItem; + } + } + + public List FreezeEvents; + public List ThawEvents; + public Part partRef; + public bool IsRTModInstalled; + public DeepFreezer freezerModuleRef; + + public CryopodEvents(Part partRef, DeepFreezer freezerRef) + { + FreezeEvents = new List(); + ThawEvents = new List(); + this.partRef = partRef; + IsRTModInstalled = DFInstalledMods.IsRTInstalled; + freezerModuleRef = freezerRef; + } + + public bool ContainsFreezeEvent(BaseEvent freezeEvent) + { + for (int i = 0; i < FreezeEvents.Count; i++) + { + if (FreezeEvents[i].eventItem.name == freezeEvent.name) + { + return true; + } + } + return false; + } + + public bool ContainsFreezeEvent(string kerbalName, out BaseEvent returnEvent) + { + returnEvent = null; + for (int i = 0; i < FreezeEvents.Count; i++) + { + if (FreezeEvents[i].kerbalName == kerbalName) + { + returnEvent = FreezeEvents[i].eventItem; + return true; + } + } + return false; + } + + public bool ContainsThawEvent(BaseEvent thawEvent) + { + for (int i = 0; i < ThawEvents.Count; i++) + { + if (ThawEvents[i].eventItem.name == thawEvent.name) + { + return true; + } + } + return false; + } + + public bool ContainsThawEvent(string kerbalName, out BaseEvent returnEvent) + { + returnEvent = null; + for (int i = 0; i < ThawEvents.Count; i++) + { + if (ThawEvents[i].kerbalName == kerbalName) + { + returnEvent = ThawEvents[i].eventItem; + return true; + } + } + return false; + } + + public void RemoveFreezeEvent(BaseEvent freezeEvent) + { + if (partRef != null) + { + partRef.Events.Remove(freezeEvent); + } + for (int i = 0; i < FreezeEvents.Count; i++) + { + if (FreezeEvents[i].eventItem == freezeEvent) + { + FreezeEvents.RemoveAt(i); + break; + } + } + } + + public bool RemoveFreezeEvent(string kerbalName) + { + for (int i = 0; i < FreezeEvents.Count; i++) + { + if (FreezeEvents[i].kerbalName == kerbalName) + { + if (partRef != null) + { + partRef.Events.Remove(FreezeEvents[i].eventItem); + } + FreezeEvents.RemoveAt(i); + return true; + } + } + return false; + } + + public void RemoveThawEvent(BaseEvent thawEvent) + { + if (partRef != null) + { + partRef.Events.Remove(thawEvent); + } + for (int i = 0; i < ThawEvents.Count; i++) + { + if (ThawEvents[i].eventItem == thawEvent) + { + ThawEvents.RemoveAt(i); + break; + } + } + } + + public bool RemoveThawEvent(string kerbalName) + { + for (int i = 0; i < ThawEvents.Count; i++) + { + if (ThawEvents[i].kerbalName == kerbalName) + { + if (partRef != null) + { + partRef.Events.Remove(ThawEvents[i].eventItem); + } + ThawEvents.RemoveAt(i); + return true; + } + } + return false; + } + + private void AddFreezeEvent(string kerbalName, BaseEvent eventItem, bool addToPart) + { + BaseEvent eventData = null; + if (!ContainsFreezeEvent(kerbalName, out eventData)) + { + EventData newItem = new EventData(kerbalName, eventItem); + FreezeEvents.Add(newItem); + if (addToPart && partRef != null) + { + partRef.Events.AddUnique(eventItem); + } + } + } + + private void AddThawEvent(string kerbalName, BaseEvent eventItem, bool addToPart) + { + BaseEvent eventData = null; + if (!ContainsThawEvent(kerbalName, out eventData)) + { + EventData newItem = new EventData(kerbalName, eventItem); + ThawEvents.Add(newItem); + if (addToPart && partRef != null) + { + partRef.Events.AddUnique(eventItem); + } + } + } + + public void AddFreezeEvent(string kerbalName, bool addToPart) + { + if (partRef == null) + { + return; + } + BaseEvent eventData = null; + if (!ContainsFreezeEvent(kerbalName, out eventData)) + { + ProtoCrewMember kerbal = null; + for (int j = 0; j < partRef.protoModuleCrew.Count; j++) + { + if (partRef.protoModuleCrew[j].name == kerbalName) + { + kerbal = partRef.protoModuleCrew[j]; + break; + } + } + if (kerbal != null) + { + BaseEvent newEvent = createFreezeEvent(kerbal); + if (newEvent != null) + { + EventData newItem = new EventData(kerbalName, newEvent); + FreezeEvents.Add(newItem); + if (addToPart && partRef != null) + { + partRef.Events.AddUnique(newEvent); + } + } + } + } + } + + public void AddThawEvent(string kerbalName, bool addToPart) + { + BaseEvent eventData = null; + if (!ContainsThawEvent(kerbalName, out eventData)) + { + BaseEvent newEvent = createThawEvent(kerbalName); + if (newEvent != null) + { + EventData newItem = new EventData(kerbalName, newEvent); + ThawEvents.Add(newItem); + if (addToPart && partRef != null) + { + partRef.Events.AddUnique(newEvent); + } + } + } + } + + public void RemoveAllEventsFromPart() + { + if (partRef == null) + { + return; + } + for (int i = 0; i < ThawEvents.Count; i++) + { + partRef.Events.Remove(ThawEvents[i].eventItem); + } + for (int i = 0; i < FreezeEvents.Count; i++) + { + partRef.Events.Remove(FreezeEvents[i].eventItem); + } + } + + public void AddAllEventsToPart() + { + if (partRef == null) + { + return; + } + RemoveAllEventsFromPart(); + for (int i = 0; i < ThawEvents.Count; i++) + { + partRef.Events.Add(ThawEvents[i].eventItem); + } + for (int i = 0; i < FreezeEvents.Count; i++) + { + partRef.Events.Add(FreezeEvents[i].eventItem); + } + } + + private BaseEvent createFreezeEvent(ProtoCrewMember kerbal) + { + if (partRef == null || freezerModuleRef == null) + { + return null; + } + return new BaseEvent(partRef.Events, "Freeze " + kerbal.name, () => + { + freezerModuleRef.beginFreezeKerbal(kerbal); + }, new KSPEvent { guiName = Localizer.Format("#autoLOC_DF_00199", kerbal.name), guiActive = true }); + } + + private BaseEvent createThawEvent(string kerbalName) + { + if (partRef == null || freezerModuleRef == null) + { + return null; + } + return new BaseEvent(partRef.Events, "Thaw " + kerbalName, () => + { + freezerModuleRef.beginThawKerbal(kerbalName); + }, new KSPEvent { guiName = Localizer.Format("#autoLOC_DF_00200", kerbalName), guiActive = true }); + } + + + public void SyncEvents() + { + //Check Freeze and Thaw Events are for Kerbals still in the Vessel. + if (partRef == null || freezerModuleRef == null) + { + return; + } + //If RemoteTech is installed show or don't show all the events, depending on connection state. + if (IsRTModInstalled) + { + if (!freezerModuleRef.isRTConnected) + { + RemoveAllEventsFromPart(); + return; + } + else + { + AddAllEventsToPart(); + } + } + + FrznCrewList frozenCrew = freezerModuleRef.DFIStoredCrewList; + //Check the ThawEvents against the frozen crew list in the PartModule and Remove Thaw events for kerbals that aren't in the frozen list. + for (int i = ThawEvents.Count - 1; i >= 0; i--) + { + bool found = false; + for (int j = 0; j < frozenCrew.Count; j++) + { + if (frozenCrew[j].CrewName == ThawEvents[i].kerbalName) + { + found = true; + break; + } + } + if (!found) //We didn't find a match. remove the ThawEvent. + { + RemoveThawEvent(ThawEvents[i].kerbalName); + } + } + //Check the FreezeEvents against the part's crew list and Remove Freeze events for kerbals that aren't in the part. + for (int i = FreezeEvents.Count - 1; i >= 0; i--) + { + bool found = false; + for (int j = 0; j < partRef.protoModuleCrew.Count; j++) + { + if (partRef.protoModuleCrew[j].name == FreezeEvents[i].kerbalName) + { + found = true; + break; + } + } + if (!found) //We didn't find a match. remove the ThawEvent. + { + RemoveFreezeEvent(FreezeEvents[i].kerbalName); + } + } + + //Check the Stored Crew (frozen) against the ThawEvents list and Add missing Thaw Event items. + for (int i = 0; i < frozenCrew.Count; i++) + { + BaseEvent eventData = null; + if (!ContainsThawEvent(frozenCrew[i].CrewName, out eventData)) + { + BaseEvent newEvent = createThawEvent(frozenCrew[i].CrewName); + if (newEvent != null) + { + AddThawEvent(frozenCrew[i].CrewName, newEvent, true); + } + } + } + //Check the Crew in the part against the FreezeEvents list and Add missing Freeze Event items. + for (int i = 0; i < partRef.protoModuleCrew.Count; i++) + { + BaseEvent eventData = null; + if (!ContainsFreezeEvent(partRef.protoModuleCrew[i].name, out eventData)) + { + BaseEvent newEvent = createFreezeEvent(partRef.protoModuleCrew[i]); + if (newEvent != null) + { + AddFreezeEvent(partRef.protoModuleCrew[i].name, newEvent, true); + } + } + } + UIPartActionWindow window = UIPartActionController.Instance.GetItem(partRef); + if (window != null) + { + window.displayDirty = true; + } + } + } +} diff --git a/Source/DFSettings.cs b/Source/DFSettings.cs new file mode 100644 index 0000000..f689324 --- /dev/null +++ b/Source/DFSettings.cs @@ -0,0 +1,250 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Collections.Generic; +using BackgroundResources; +using DeepFreeze; +using RSTUtils; + +namespace DF +{ + internal class DFSettings + { + // this class stores the DeepFreeze Settings from the config file. + private const string configNodeName = "DFSettings"; + + internal float DFwindowPosX ; + internal float DFwindowPosY ; + //internal float CFwindowPosX ; + //internal float CFwindowPosY ; + internal float DFKACwindowPosX ; + internal float DFKACwindowPosY ; + internal bool UseAppLauncher ; + internal bool debugging ; + internal bool ECreqdForFreezer ; + internal bool backgroundresources; + internal bool fatalOption ; + internal float comatoseTime ; + internal bool AutoRecoverFznKerbals ; + internal float KSCcostToThawKerbal ; + internal int ECReqdToFreezeThaw ; + internal int GlykerolReqdToFreeze ; + internal bool RegTempReqd ; + internal double RegTempFreeze ; + internal double RegTempMonitor ; + internal double heatamtMonitoringFrznKerbals ; + internal double heatamtThawFreezeKerbal ; + internal bool TempinKelvin ; + internal double defaultTimeoutforCrewXfer ; + internal double cryopodResettimeDelay ; + internal float DFWindowWidth ; + internal float CFWindowWidth ; + internal float KACWindowWidth ; + internal float WindowbaseHeight ; + internal float ECLowWarningTime ; + internal float EClowCriticalTime ; + internal bool StripLightsActive ; + internal bool BeepSoundsActive; + internal bool OtherSoundsActive; + internal int internalFrzrCamCode ; + internal int internalNxtFrzrCamCode ; + internal int internalPrvFrzrCamCode ; + internal bool ToolTips ; + internal bool EditorFilter; + + internal DFSettings() + { + DFwindowPosX = 40; + DFwindowPosY = 50; + //CFwindowPosX = 500; + //CFwindowPosY = 140; + DFKACwindowPosX = 600; + DFKACwindowPosY = 50; + UseAppLauncher = true; + debugging = true; + ECreqdForFreezer = true; + backgroundresources = true; + fatalOption = true; + comatoseTime = 300; + AutoRecoverFznKerbals = true; + KSCcostToThawKerbal = 10000f; + ECReqdToFreezeThaw = 3000; + GlykerolReqdToFreeze = 5; + RegTempReqd = false; + RegTempFreeze = 300f; + RegTempMonitor = 400f; + heatamtMonitoringFrznKerbals = 10f; + heatamtThawFreezeKerbal = 100f; + TempinKelvin = true; + defaultTimeoutforCrewXfer = 30; + cryopodResettimeDelay = 2; + DFWindowWidth = 560f; + CFWindowWidth = 340f; + KACWindowWidth = 485f; + ECLowWarningTime = 3600f; + EClowCriticalTime = 900f; + StripLightsActive = true; + BeepSoundsActive = true; + OtherSoundsActive = true; + internalFrzrCamCode = 100; + internalNxtFrzrCamCode = 110; + internalPrvFrzrCamCode = 98; + ToolTips = true; + EditorFilter = true; + } + + //Settings Functions Follow + + internal void Load(ConfigNode node) + { + if (node.HasNode(configNodeName)) + { + ConfigNode DFsettingsNode = node.GetNode(configNodeName); + + DFsettingsNode.TryGetValue("DFwindowPosX", ref DFwindowPosX); + DFsettingsNode.TryGetValue("DFwindowPosY", ref DFwindowPosY); + DFsettingsNode.TryGetValue("DFKACwindowPosX", ref DFKACwindowPosX); + DFsettingsNode.TryGetValue("DFKACwindowPosY", ref DFKACwindowPosY); + DFsettingsNode.TryGetValue("defaultTimeoutforCrewXfer", ref defaultTimeoutforCrewXfer); + DFsettingsNode.TryGetValue("cryopodResettimeDelay", ref cryopodResettimeDelay); + DFsettingsNode.TryGetValue("DFWindowWidth", ref DFWindowWidth); + DFsettingsNode.TryGetValue("CFWindowWidth", ref CFWindowWidth); + DFsettingsNode.TryGetValue("KACWindowWidth", ref KACWindowWidth); + DFsettingsNode.TryGetValue("ECLowWarningTime", ref ECLowWarningTime); + DFsettingsNode.TryGetValue("EClowCriticalTime", ref EClowCriticalTime); + DFsettingsNode.TryGetValue("internalFrzrCamCode", ref internalFrzrCamCode); + DFsettingsNode.TryGetValue("internalNxtFrzrCamCode", ref internalNxtFrzrCamCode); + DFsettingsNode.TryGetValue("internalPrvFrzrCamCode", ref internalPrvFrzrCamCode); + + + ApplySettings(); + } + } + + internal void Save(ConfigNode node) + { + ConfigNode settingsNode; + if (node.HasNode(configNodeName)) + { + settingsNode = node.GetNode(configNodeName); + settingsNode.ClearData(); + } + else + { + settingsNode = node.AddNode(configNodeName); + } + + settingsNode.AddValue("DFwindowPosX", DFwindowPosX); + settingsNode.AddValue("DFwindowPosY", DFwindowPosY); + settingsNode.AddValue("DFKACwindowPosX", DFKACwindowPosX); + settingsNode.AddValue("DFKACwindowPosY", DFKACwindowPosY); + settingsNode.AddValue("defaultTimeoutforCrewXfer", defaultTimeoutforCrewXfer); + settingsNode.AddValue("cryopodResettimeDelay", cryopodResettimeDelay); + settingsNode.AddValue("DFWindowWidth", DFWindowWidth); + settingsNode.AddValue("CFWindowWidth", CFWindowWidth); + settingsNode.AddValue("KACWindowWidth", KACWindowWidth); + settingsNode.AddValue("ECLowWarningTime", ECLowWarningTime); + settingsNode.AddValue("EClowCriticalTime", EClowCriticalTime); + settingsNode.AddValue("internalFrzrCamCode", internalFrzrCamCode); + settingsNode.AddValue("internalNxtFrzrCamCode", internalNxtFrzrCamCode); + settingsNode.AddValue("internalPrvFrzrCamCode", internalPrvFrzrCamCode); + + Utilities.Log_Debug("DFSettings save complete"); + } + + internal void ApplySettings() + { + Utilities.Log_Debug("DFSettings ApplySettings Start"); + if (HighLogic.CurrentGame != null) + { + var DF_SettingsParms = HighLogic.CurrentGame.Parameters.CustomParams(); + var DF_SettingsParms_Sec2 = HighLogic.CurrentGame.Parameters.CustomParams(); + var DF_SettingsParms_Sec3 = HighLogic.CurrentGame.Parameters.CustomParams(); + if (DF_SettingsParms != null) + { + var GUI = + DeepFreeze.Instance.children.Find(a => a.GetType() == typeof(DeepFreezeGUI)) as DeepFreezeGUI; + if (ECreqdForFreezer != DF_SettingsParms.ECreqdForFreezer) + { + if (GUI != null) + { + GUI.chgECHeatsettings = true; + GUI.chgECHeatsettingsTimer = Planetarium.GetUniversalTime(); + } + } + ECreqdForFreezer = DF_SettingsParms.ECreqdForFreezer; + //If user switches off backgroundresources - and it was on. remove background processing if in loaded game. + if (backgroundresources && !DF_SettingsParms.backgroundresources && DFInstalledMods.IsBGRInstalled && UnloadedResources.Instance && DeepFreeze.Instance && HighLogic.LoadedSceneIsGame) + { + List> knownVessels = DeepFreeze.Instance.KnownVesselsList; + for (int i = 0; i < knownVessels.Count; i++) + { + UnloadedResources.Instance.RemoveInterestedVessel(knownVessels[i].Key); + } + } + backgroundresources = DF_SettingsParms.backgroundresources; + fatalOption = DF_SettingsParms.fatalOption; + comatoseTime = DF_SettingsParms.comatoseTime; + if (UseAppLauncher != DF_SettingsParms_Sec3.UseAppLToolbar) + { + UseAppLauncher = DF_SettingsParms_Sec3.UseAppLToolbar; + + if (GUI != null) + { + GUI.DFMenuAppLToolBar.chgAppIconStockToolBar(UseAppLauncher); + } + } + debugging = DF_SettingsParms_Sec3.DebugLogging; + Utilities.debuggingOn = debugging; + ToolTips = DF_SettingsParms_Sec3.ToolTips; + AutoRecoverFznKerbals = DF_SettingsParms.AutoRecoverFznKerbals; + KSCcostToThawKerbal = DF_SettingsParms.KSCcostToThawKerbal; + ECReqdToFreezeThaw = DF_SettingsParms.ECReqdToFreezeThaw; + GlykerolReqdToFreeze = DF_SettingsParms.GlykerolReqdToFreeze; + if (RegTempReqd != DF_SettingsParms_Sec2.RegTempReqd) + { + if (GUI != null) + { + GUI.chgECHeatsettings = true; + GUI.chgECHeatsettingsTimer = Planetarium.GetUniversalTime(); + } + } + RegTempReqd = DF_SettingsParms_Sec2.RegTempReqd; + RegTempFreeze = DF_SettingsParms_Sec2.RegTempFreeze; + RegTempMonitor = DF_SettingsParms_Sec2.RegTempMonitor; + heatamtMonitoringFrznKerbals = DF_SettingsParms_Sec2.heatamtMonitoringFrznKerbals; + TempinKelvin = DF_SettingsParms_Sec2.TempinKelvin; + StripLightsActive = DF_SettingsParms_Sec3.StripLightsActive; + BeepSoundsActive = DF_SettingsParms_Sec3.BeepSoundsActive; + OtherSoundsActive = DF_SettingsParms_Sec3.OtherSoundsActive; + if (EditorFilter != DF_SettingsParms_Sec3.EditorFilter) + { + EditorFilter = DF_SettingsParms_Sec3.EditorFilter; + if (DFEditorFilter.Instance != null) + DFEditorFilter.Instance.Setup(); + } + } + else + Utilities.Log_Debug("DFSettings ApplySettings Settings Params Not Set!"); + } + else + Utilities.Log_Debug("DFSettings ApplySettings CurrentGame is NULL!"); + Utilities.Log_Debug("DFSettings ApplySettings End"); + } + } +} \ No newline at end of file diff --git a/Source/DeeFreezeEvents.cs b/Source/DeeFreezeEvents.cs deleted file mode 100644 index 260e090..0000000 --- a/Source/DeeFreezeEvents.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; -using DeepFreezer; - - -namespace DeepFreezer -{ - class DeepFreezeEvents - { - - public static DeepFreezeEvents instance = new DeepFreezeEvents(); - public bool eventAdded; - - public DeepFreezeEvents() - { - //Debug.Log("DeepFreezeEvents"); - eventAdded = false; - } - - public void DeepFreezeEventAdd() - { - Debug.Log("DeepFreezeEventAdd"); - GameEvents.OnVesselRecoveryRequested.Add(this.OnVesselRecoveryRequested); - GameEvents.onVesselRecovered.Add(this.onVesselRecovered); - GameEvents.onVesselTerminated.Add(this.onVesselTerminated); - GameEvents.onVesselWillDestroy.Add(this.onVesselWillDestroy); - eventAdded = true; - } - - - public void OnVesselRecoveryRequested(Vessel vessel) - { - Debug.Log("OnVesselRecoveryRequested"); - if (vessel.FindPartModulesImplementing().Count > 0) - { - foreach (DeepFreezer freezer in vessel.FindPartModulesImplementing()) - { - freezer.part.CrewCapacity = freezer.StoredCrew.Count; - foreach (var crewmember in freezer.StoredCrew) - { - foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) - { - if (kerbal.name == crewmember) - { - freezer.part.AddCrewmember(kerbal); - Debug.Log("Crew Added" + kerbal.name); - } - } - - } - } - } - } - - public void onVesselRecovered(ProtoVessel vessel) - { - //Debug.Log("onVesselRecovered"); - List partList = vessel.protoPartSnapshots; - foreach (ProtoPartSnapshot a in partList) - { - //Debug.Log(a.partName); - List modules = a.modules; - foreach (ProtoPartModuleSnapshot module in modules) - { - //Debug.Log(module.moduleName); - if (module.moduleName == "DeepFreezer") - { - ConfigNode node = module.moduleValues; - string FrozenCrew = node.GetValue("FrozenCrew"); - Debug.Log(FrozenCrew); - ThawFrozenCrew(FrozenCrew); - } - } - } - } - - - public void onVesselTerminated(ProtoVessel vessel) - { - List partList = vessel.protoPartSnapshots; - foreach (ProtoPartSnapshot a in partList) - { - List modules = a.modules; - foreach (ProtoPartModuleSnapshot module in modules) - { - - if (module.moduleName == "DeepFreezer") - { - ConfigNode node = module.moduleValues; - string FrozenCrew = node.GetValue("FrozenCrew"); - KillFrozenCrew(FrozenCrew); - } - } - } - } - - public void onVesselWillDestroy(Vessel vessel) - { - ProtoVessel pvessel; - pvessel = vessel.protoVessel; - List partList = pvessel.protoPartSnapshots; - foreach (ProtoPartSnapshot a in partList) - { - List modules = a.modules; - foreach (ProtoPartModuleSnapshot module in modules) - { - - if (module.moduleName == "DeepFreezer") - { - ConfigNode node = module.moduleValues; - string FrozenCrew = node.GetValue("FrozenCrew"); - KillFrozenCrew(FrozenCrew); - } - } - } - } - - - - public void ThawFrozenCrew(String FrozenCrew) - { - List StoredCrew = FrozenCrew.Split(',').ToList(); - foreach (string frozenkerbal in StoredCrew) - { - foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) //There's probably a more efficient way to find Protocrewmember from the CrewRoster - { - if (kerbal.name == frozenkerbal) - { - kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Available; - ScreenMessages.PostScreenMessage(kerbal.name + " was found in and thawed out.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - } - } - } - } - public void KillFrozenCrew(string FrozenCrew) - { - List StoredCrew = FrozenCrew.Split(',').ToList(); - foreach (string frozenkerbal in StoredCrew) - { - foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) - { - if (kerbal.name == frozenkerbal) - { - Debug.Log(kerbal.name + " killed"); - if (HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn == true) - { - kerbal.StartRespawnPeriod(); - Debug.Log(kerbal.name + " respawn started."); - } - } - } - } - } - - - - - - - } -} diff --git a/Source/DeepFreeze.cs b/Source/DeepFreeze.cs new file mode 100644 index 0000000..7433030 --- /dev/null +++ b/Source/DeepFreeze.cs @@ -0,0 +1,543 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using BackgroundResources; +using RSTUtils; +using UnityEngine; +using KSP.Localization; + +namespace DF +{ + [KSPScenario(ScenarioCreationOptions.AddToAllGames, GameScenes.SPACECENTER, GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.TRACKSTATION)] + public class DeepFreeze : ScenarioModule + { + public static DeepFreeze Instance; + public static bool APIReady; + internal DFSettings DFsettings; + internal DFGameSettings DFgameSettings; + private readonly string globalConfigFilename; + private ConfigNode globalNode = new ConfigNode(); + internal readonly List children = new List(); + private List> _frozenKerbalsList = new List>(); + private List> _knownVesselList = new List>(); + private List> _knownFreezerPartsList = new List>(); + + public bool DFIECReqd + { + get { return DFsettings.ECreqdForFreezer; } + } + + public bool DFIDeathFatal + { + get { return DFsettings.fatalOption; } + } + + public Dictionary FrozenKerbals + { + get + { + return DFgameSettings.KnownFrozenKerbals; + } + } + + public Dictionary KnownVessels + { + get + { + return DFgameSettings.knownVessels; + } + } + + public List> KnownVesselsList + { + get + { + _knownVesselList.Clear(); + _knownVesselList = DFgameSettings.knownVessels.ToList(); + return _knownVesselList; + } + } + + public Dictionary KnownFreezerParts + { + get + { + return DFgameSettings.knownFreezerParts; + } + } + + public List> KnownFreezerPartsList + { + get + { + _knownFreezerPartsList.Clear(); + _knownFreezerPartsList = DFgameSettings.knownFreezerParts.ToList(); + return _knownFreezerPartsList; + } + } + + public List> FrozenKerbalsList + { + get + { + _frozenKerbalsList.Clear(); + _frozenKerbalsList = DFgameSettings.KnownFrozenKerbals.ToList(); + return _frozenKerbalsList; + } + } + + public DeepFreeze() + { + //Utilities.Log("DeepFreeze Constructor"); + Instance = this; + APIReady = false; + DFsettings = new DFSettings(); + DFgameSettings = new DFGameSettings(); + globalConfigFilename = Path.Combine(_AssemblyFolder, "PluginData/Config.cfg").Replace("\\", "/"); + //Utilities.Log("globalConfigFilename = " + globalConfigFilename); + DeepFreezeEventAdd(); + } + + public override void OnAwake() + { + Utilities.Log("OnAwake in " + HighLogic.LoadedScene); + base.OnAwake(); + + GameEvents.onGameSceneLoadRequested.Add(OnGameSceneLoadRequested); + GameEvents.OnGameSettingsApplied.Add(ApplySettings); + + if (HighLogic.LoadedScene == GameScenes.SPACECENTER) + { + Utilities.Log("Adding SpaceCenterManager"); + var DFMem = gameObject.AddComponent(); + children.Add(DFMem); + var child = gameObject.AddComponent(); + children.Add(child); + } + else if (HighLogic.LoadedScene == GameScenes.FLIGHT) + { + Utilities.Log("Adding FlightManager"); + var DFMem = gameObject.AddComponent(); + children.Add(DFMem); + var child = gameObject.AddComponent(); + children.Add(child); + } + else if (HighLogic.LoadedScene == GameScenes.EDITOR) + { + Utilities.Log("Adding EditorController"); + var DFMem = gameObject.AddComponent(); + children.Add(DFMem); + + //var child = gameObject.AddComponent(); + //children.Add(child); + } + else if (HighLogic.LoadedScene == GameScenes.TRACKSTATION) + { + Utilities.Log("Adding TrackingStationController"); + var DFMem = gameObject.AddComponent(); + children.Add(DFMem); + var child = gameObject.AddComponent(); + children.Add(child); + } + + + } + + public override void OnLoad(ConfigNode gameNode) + { + base.OnLoad(gameNode); + DFgameSettings.Load(gameNode); + // Load the global settings + if (File.Exists(globalConfigFilename)) + { + globalNode = ConfigNode.Load(globalConfigFilename); + DFsettings.Load(globalNode); + foreach (Savable s in children.Where(c => c is Savable)) + { + s.Load(globalNode); + } + } + if (HighLogic.LoadedScene == GameScenes.SPACECENTER) + { + DFEditorFilter.Instance.Setup(); + } + Utilities.debuggingOn = DFsettings.debugging; + APIReady = true; + if (Utilities.debuggingOn) + Debug.Log("Scenario: " + HighLogic.LoadedScene + " OnLoad: \n " + gameNode + "\n" + globalNode); + else + { + Debug.Log("DeepFreeze Scenario Onload Completed."); + } + } + + public override void OnSave(ConfigNode gameNode) + { + //APIReady = false; + base.OnSave(gameNode); + DFgameSettings.Save(gameNode); + foreach (Savable s in children.Where(c => c is Savable)) + { + s.Save(globalNode); + } + DFsettings.Save(globalNode); + globalNode.Save(globalConfigFilename); + if (Utilities.debuggingOn) + Debug.Log("Scenario: " + HighLogic.LoadedScene + " OnSave: \n" + gameNode + "\n" + globalNode); + else + { + Debug.Log("DeepFreeze Scenario OnSave completed."); + } + } + + + + protected void OnDestroy() + { + Utilities.Log("OnDestroy"); + Instance = null; + APIReady = false; + foreach (Component child in children) + { + Utilities.Log("DeepFreeze Child Destroy for " + child.name); + Destroy(child); + } + children.Clear(); + DeepFreezeEventRem(); + GameEvents.onGameSceneLoadRequested.Remove(OnGameSceneLoadRequested); + GameEvents.OnGameSettingsApplied.Remove(ApplySettings); + } + + #region Events + + public void ApplySettings() + { + if (DFsettings != null) + { + DFsettings.ApplySettings(); + } + } + + protected void OnGameSceneLoadRequested(GameScenes gameScene) + { + //Utilities.Log("Game scene load requested: " + gameScene); + } + + protected void DeepFreezeEventAdd() + { + //Utilities.Log("DeepFreezeEvents DeepFreezeEventAdd"); + GameEvents.onVesselRecovered.Add(onVesselRecovered); + GameEvents.onVesselTerminated.Add(onVesselTerminated); + GameEvents.onVesselWillDestroy.Add(onVesselWillDestroy); + //Utilities.Log("DeepFreezeEvents DeepFreezeEventAdd ended"); + } + + protected void DeepFreezeEventRem() + { + //Utilities.Log("DeepFreezeEvents DeepFreezeEventRem"); + GameEvents.onVesselRecovered.Remove(onVesselRecovered); + GameEvents.onVesselTerminated.Remove(onVesselTerminated); + GameEvents.onVesselWillDestroy.Remove(onVesselWillDestroy); + //Utilities.Log("DeepFreezeEvents DeepFreezeEventRem ended"); + } + + protected void onVesselRecovered(ProtoVessel vessel, bool notSureWhatFor) + { + Utilities.Log("DeepFreezeEvents onVesselRecovered " + vessel.vesselID); + List frznKerbalkeys = new List(DFgameSettings.KnownFrozenKerbals.Keys); + foreach (string key in frznKerbalkeys) + { + KerbalInfo kerbalinfo = DFgameSettings.KnownFrozenKerbals[key]; + if (kerbalinfo.vesselID == vessel.vesselID) + { + if (kerbalinfo.type == ProtoCrewMember.KerbalType.Unowned) //Frozen crew + { + if (Instance.DFsettings.AutoRecoverFznKerbals) + { + Utilities.Log_Debug("AutoRecover is ON"); + Utilities.Log("Calling ThawFrozen Crew to thaw FrozenCrew " + key); + ThawFrozenCrew(key, vessel.vesselID); + } + else + { + Utilities.Log("DeepFreeze AutoRecovery of frozen kerbals is set to off. Must be thawed manually."); + Utilities.Log("DeepFreezeEvents frozenkerbal remains frozen =" + key); + ProtoCrewMember realkerbal = HighLogic.CurrentGame.CrewRoster.Unowned.FirstOrDefault(b => b.name == key); + if (realkerbal != null) + { + realkerbal.type = ProtoCrewMember.KerbalType.Unowned; + realkerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; + Utilities.Log_Debug("Kerbal " + realkerbal.name + " " + realkerbal.type + " " + realkerbal.rosterStatus); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00049", key), 5.0f, ScreenMessageStyle.UPPER_LEFT); + } + } + } + else // Tourist/Comatose crew + { + Utilities.Log_Debug("Comatose crew - reset to crew " + key); + ProtoCrewMember crew = HighLogic.CurrentGame.CrewRoster.Tourist.FirstOrDefault(c => c.name == key); + if (crew != null) + { + crew.type = ProtoCrewMember.KerbalType.Crew; + crew.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; + Utilities.Log_Debug("Kerbal " + crew.name + " " + crew.type + " " + crew.rosterStatus); + crew.ArchiveFlightLog(); + crew.rosterStatus = ProtoCrewMember.RosterStatus.Available; + DFgameSettings.KnownFrozenKerbals.Remove(crew.name); + } + } + } + } + var alarmsToDelete = new List(); + alarmsToDelete.AddRange(Instance.DFgameSettings.knownKACAlarms.Where(e => e.Value.VesselID == vessel.vesselID).Select(e => e.Key).ToList()); + alarmsToDelete.ForEach(id => Instance.DFgameSettings.knownKACAlarms.Remove(id)); + var partsToDelete = new List(); + partsToDelete.AddRange(Instance.DFgameSettings.knownFreezerParts.Where(e => e.Value.vesselID == vessel.vesselID).Select(e => e.Key).ToList()); + partsToDelete.ForEach(id => Instance.DFgameSettings.knownFreezerParts.Remove(id)); + if (DFInstalledMods.IsBGRInstalled && DeepFreeze.Instance.DFsettings.backgroundresources) + { + if (UnloadedResources.Instance != null) + { + UnloadedResources.Instance.RemoveInterestedVessel(vessel); + } + } + if (DFgameSettings.knownVessels.ContainsKey(vessel.vesselID)) + { + DFgameSettings.knownVessels.Remove(vessel.vesselID); + } + } + + protected void onVesselTerminated(ProtoVessel vessel) + { + Utilities.Log("DeepFreezeEvents onVesselTerminated " + vessel.vesselID); + foreach (KeyValuePair kerbal in Instance.DFgameSettings.KnownFrozenKerbals) + { + if (kerbal.Value.vesselID == vessel.vesselID) + { + KillFrozenCrew(kerbal.Key); + } + } + var alarmsToDelete = new List(); + alarmsToDelete.AddRange(Instance.DFgameSettings.knownKACAlarms.Where(e => e.Value.VesselID == vessel.vesselID).Select(e => e.Key).ToList()); + alarmsToDelete.ForEach(id => Instance.DFgameSettings.knownKACAlarms.Remove(id)); + var partsToDelete = new List(); + partsToDelete.AddRange(Instance.DFgameSettings.knownFreezerParts.Where(e => e.Value.vesselID == vessel.vesselID).Select(e => e.Key).ToList()); + partsToDelete.ForEach(id => Instance.DFgameSettings.knownFreezerParts.Remove(id)); + if (DFInstalledMods.IsBGRInstalled && DeepFreeze.Instance.DFsettings.backgroundresources) + { + if (UnloadedResources.Instance != null) + { + UnloadedResources.Instance.RemoveInterestedVessel(vessel); + } + } + if (DFgameSettings.knownVessels.ContainsKey(vessel.vesselID)) + { + DFgameSettings.knownVessels.Remove(vessel.vesselID); + } + } + + protected void onVesselWillDestroy(Vessel vessel) + { + Utilities.Log("DeepFreezeEvents onVesselWillDestroy " + vessel.id); + foreach (KeyValuePair kerbal in Instance.DFgameSettings.KnownFrozenKerbals) + { + if (kerbal.Value.vesselID == vessel.id) + { + KillFrozenCrew(kerbal.Key); + } + } + var alarmsToDelete = new List(); + alarmsToDelete.AddRange(Instance.DFgameSettings.knownKACAlarms.Where(e => e.Value.VesselID == vessel.id).Select(e => e.Key).ToList()); + alarmsToDelete.ForEach(id => Instance.DFgameSettings.knownKACAlarms.Remove(id)); + var partsToDelete = new List(); + partsToDelete.AddRange(Instance.DFgameSettings.knownFreezerParts.Where(e => e.Value.vesselID == vessel.id).Select(e => e.Key).ToList()); + partsToDelete.ForEach(id => Instance.DFgameSettings.knownFreezerParts.Remove(id)); + if (DFInstalledMods.IsBGRInstalled && DeepFreeze.Instance.DFsettings.backgroundresources) + { + if (UnloadedResources.Instance != null) + { + UnloadedResources.Instance.RemoveInterestedVessel(vessel.id); + } + } + if (DFgameSettings.knownVessels.ContainsKey(vessel.id)) + { + DFgameSettings.knownVessels.Remove(vessel.id); + } + } + + internal void ThawFrozenCrew(String FrozenCrew, Guid vesselID) + { + Utilities.Log("DeepFreezeEvents ThawFrozenCrew = " + FrozenCrew + "," + vesselID); + bool fundstaken = false; + ProtoCrewMember kerbal = HighLogic.CurrentGame.CrewRoster.Unowned.FirstOrDefault(a => a.name == FrozenCrew); + if (kerbal != null) + { + Vessel vessel = FlightGlobals.Vessels.Find(v => v.id == vesselID); + // Utilities.Log_Debug("vessel mainbody" + vessel.mainBody.name + " is homeworld? " + vessel.mainBody.isHomeWorld); + + if (vessel == null || + (vessel.mainBody.isHomeWorld + && (vessel.situation == Vessel.Situations.LANDED || vessel.situation == Vessel.Situations.PRELAUNCH || vessel.situation == Vessel.Situations.SPLASHED))) + { + if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) + { + if (Funding.CanAfford(DFsettings.KSCcostToThawKerbal)) + { + Funding.Instance.AddFunds(-DFsettings.KSCcostToThawKerbal, TransactionReasons.Vessels); + fundstaken = true; + Utilities.Log("Took funds to thaw kerbal"); + } + else + { + Utilities.Log("Not enough funds to thaw kerbal"); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00050", kerbal.name), 5.0f, ScreenMessageStyle.UPPER_LEFT); + return; + } + } + kerbal.type = ProtoCrewMember.KerbalType.Crew; + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; + Utilities.Log_Debug("Kerbal " + kerbal.name + " " + kerbal.type + " " + kerbal.rosterStatus); + kerbal.ArchiveFlightLog(); + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Available; + Utilities.Log_Debug("Kerbal " + kerbal.name + " " + kerbal.type + " " + kerbal.rosterStatus); + if (!fundstaken) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00051", kerbal.name), 5.0f, ScreenMessageStyle.UPPER_LEFT); + } + else + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00052", kerbal.name, DFsettings.KSCcostToThawKerbal.ToString("########0")), 5.0f, ScreenMessageStyle.UPPER_CENTER); + } + DFgameSettings.KnownFrozenKerbals.Remove(kerbal.name); + } + else + { + Utilities.Log("Cannot thaw, vessel still exists " + vessel.situation + " at " + vessel.mainBody.bodyName); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00053", kerbal.name, vessel.SituationString, vessel.mainBody.displayName), 5.0f, ScreenMessageStyle.UPPER_CENTER); + } + } + } + + public void KillFrozenCrew(string FrozenCrew) + { + Utilities.Log("DeepFreezeEvents KillFrozenCrew " + FrozenCrew); + Instance.DFgameSettings.KnownFrozenKerbals.Remove(FrozenCrew); + ProtoCrewMember kerbal = HighLogic.CurrentGame.CrewRoster.Unowned.FirstOrDefault(a => a.name == FrozenCrew); + if (kerbal != null) + { + Utilities.Log("DeepFreezeEvents " + kerbal.name + " killed"); + kerbal.type = ProtoCrewMember.KerbalType.Crew; + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; + DFGameEvents.onFrozenKerbalDied.Fire(kerbal); + if (HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn) + { + kerbal.StartRespawnPeriod(); + Utilities.Log("DeepFreezeEvents " + kerbal.name + " respawn started."); + } + } + else + { + // check if comatose crew + ProtoCrewMember crew = HighLogic.CurrentGame.CrewRoster.Tourist.FirstOrDefault(a => a.name == FrozenCrew); + if (crew != null) + { + Utilities.Log("DeepFreezeEvents " + crew.name + " killed"); + crew.type = ProtoCrewMember.KerbalType.Crew; + crew.rosterStatus = ProtoCrewMember.RosterStatus.Dead; + DFGameEvents.onFrozenKerbalDied.Fire(crew); + if (HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn) + { + crew.StartRespawnPeriod(); + Utilities.Log("DeepFreezeEvents " + crew.name + " respawn started."); + } + } + else + Utilities.Log("DeepFreezeEvents " + crew.name + " couldn't find them to kill them."); + } + } + + internal bool setComatoseKerbal(Part part, ProtoCrewMember crew, ProtoCrewMember.KerbalType type, bool start) + { + try + { + if (start) + { + crew.UnregisterExperienceTraits(part); + DFGameEvents.onKerbalSetComatose.Fire(part, crew); + } + + crew.type = type; + + if (!start) + { + crew.RegisterExperienceTraits(part); + DFGameEvents.onKerbalUnSetComatose.Fire(part, crew); + ScreenMessages.PostScreenMessage( + Localizer.Format("#autoLOC_DF_00001", crew.name), 5.0f, + ScreenMessageStyle.UPPER_CENTER); + } + else + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00002", crew.name, Instance.DFsettings.comatoseTime / 60), 5.0f, ScreenMessageStyle.UPPER_CENTER); + } + + return true; + } + catch (Exception) + { + Utilities.Log("DeepFreeze Failed to set " + crew.name + " to status of " + type + " during emergency thaw processing."); + return false; + } + } + + #endregion Events + + #region Assembly/Class Information + + /// + /// Name of the Assembly that is running this MonoBehaviour + /// + internal static String _AssemblyName + { get { return Assembly.GetExecutingAssembly().GetName().Name; } } + + /// + /// Full Path of the executing Assembly + /// + internal static String _AssemblyLocation + { get { return Assembly.GetExecutingAssembly().Location.Replace("\\", "/"); } } + + /// + /// Folder containing the executing Assembly + /// + internal static String _AssemblyFolder + { get { return Path.GetDirectoryName(_AssemblyLocation).Replace("\\", "/"); } } + + #endregion Assembly/Class Information + } + + internal interface Savable + { + void Load(ConfigNode globalNode); + + void Save(ConfigNode globalNode); + } +} \ No newline at end of file diff --git a/Source/DeepFreeze.csproj b/Source/DeepFreeze.csproj index c4f84a5..1110ff4 100644 --- a/Source/DeepFreeze.csproj +++ b/Source/DeepFreeze.csproj @@ -9,17 +9,21 @@ Properties DeepFreeze DeepFreeze - v4.5 + v4.6 512 + true full false - ..\..\Output\Plugins\ - DEBUG;TRACE + obj\Debug\ + DEBUG prompt 4 + false + Auto + false pdbonly @@ -28,33 +32,159 @@ TRACE prompt 4 + false + + + OnOutputUpdated - - C:\KSP-Dev\KSP_Data\Managed\Assembly-CSharp.dll - False + + False + ..\..\KSPDLLs\Assembly-CSharp.dll + + + False + ..\..\KSPDLLs\Assembly-CSharp-firstpass.dll + + + ..\..\REPOSoftTechKSPUtils\BackgroundResources\bin\Release\BackgroundResources.dll - - - C:\KSP-Dev\KSP_Data\Managed\UnityEngine.dll - False + + False + ..\..\KSPDLLs\UnityEngine.dll + + + ..\..\KSPDLLs\UnityEngine.AnimationModule.dll + + + ..\..\KSPDLLs\UnityEngine.AudioModule.dll + + + ..\..\KSPDLLs\UnityEngine.CoreModule.dll + + + ..\..\KSPDLLs\UnityEngine.ImageConversionModule.dll + + + ..\..\KSPDLLs\UnityEngine.IMGUIModule.dll + + + ..\..\KSPDLLs\UnityEngine.InputLegacyModule.dll + + + ..\..\KSPDLLs\UnityEngine.TextRenderingModule.dll + + + False + ..\..\KSPDLLs\UnityEngine.UI.dll - - + + AppLauncherToolBarExtension.cs + + + RectExtentions.cs + + + RSTutilities.cs + + + ToolBarManager.cs + + + + + + + + + + + + + + + + + + + + + + + + + DeepFreezeContinued.version + + + + + + + + + + + + + Changelog.txt + + + + + + + + + + + + + - - + + $(PostBuildEventDependsOn); + PostBuildMacros; + + set /p KSP_DIR=<"$(ProjectDir)LocalDev\ksp_dir.txt" + +set /p MONO_EXE_DIR=<"$(ProjectDir)LocalDev\mono_exe.txt" + +set /p PDB2MDB_EXE_DIR=<"$(ProjectDir)LocalDev\pdb2mdb_exe.txt" + +set /p ZA_DIR=<"$(ProjectDir)LocalDev\7za_dir.txt" +xcopy "$(TargetPath)" "$(SolutionDir)..\Distribution\GameData\REPOSoftTech\$(ProjectName)\Plugins\" /Y + +xcopy "$(TargetDir)$(ProjectName).pdb" "$(SolutionDir)..\Distribution\GameData\REPOSoftTech\$(ProjectName)\Plugins\" /Y + +cd "$(TargetDir)" +"%25MONO_EXE_DIR%25" "%25PDB2MDB_EXE_DIR%25" "$(TargetFileName)" +xcopy "$(TargetDir)$(ProjectName).dll.mdb" "$(SolutionDir)..\Distribution\GameData\REPOSoftTech\$(ProjectName)\Plugins\" /Y + +where /q %25ZA_DIR%25:7za.exe +if %25ERRORLEVEL%25 == 1 ( + echo Cannot find 7-zip to package build +) else ( + echo Packaging build + ) +if exist "$(SolutionDir)..\Distribution\$(ProjectName)_V@(VersionNumber).zip" del "$(SolutionDir)..\Distribution\$(ProjectName)_V@(VersionNumber).zip" +if exist "$(SolutionDir)..\GameData\" xcopy /E /Y "$(SolutionDir)..\GameData" "$(SolutionDir)..\Distribution\GameData" + +%25ZA_DIR%257za.exe a -tzip -r "$(SolutionDir)..\Distribution\$(ProjectName)_V@(VersionNumber).zip" "$(SolutionDir)..\Distribution\GameData" +cd "$(SolutionDir)..\Distribution\GameData\RepoSoftTech\$(ProjectName)\Icons" +dir /b > "$(SolutionDir)IconsExclude.txt" +c:\7za\7za d -r -x@"$(SolutionDir)IconsExclude.txt" -x!REPOSoftTech.png "$(SolutionDir)..\Distribution\$(ProjectName)_V@(VersionNumber).zip" "*.ddsified" "*.pdb" "*.mdb" "*.png" +xcopy /E /Y "$(SolutionDir)..\Distribution\GameData" "%25KSP_DIR%25\GameData\" + \ 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/DeepFreezer.cs b/Source/DeepFreezer.cs deleted file mode 100644 index a298194..0000000 --- a/Source/DeepFreezer.cs +++ /dev/null @@ -1,385 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using DeepFreezer; - - -namespace DeepFreezer -{ - [KSPAddon(KSPAddon.Startup.EveryScene, false)] - class DeepFreeze : MonoBehaviour - { - - public void Start() - { - //Debug.Log("Start called"); - if (!DeepFreezeEvents.instance.eventAdded) - //{ - DeepFreezeEvents.instance.DeepFreezeEventAdd(); - Debug.Log("!DeepFreezeEvents.instance.eventAdded"); - // } - } - - - } - public class DeepFreezer : PartModule - { - private float lastUpdate = 0.0f; - - private float updatetnterval = .5f; - - - [KSPField(isPersistant = true, guiActive = false, guiName = "FC")] //This string value is the names of frozen crew, it is turned into a list called StoredCrew during loaded. We keep this string current and it get's saved to the persistant.sfs on save. - public string FrozenCrew; - - [KSPField(isPersistant = true, guiActive = false, guiName = "Freezer Size")] //Total Size of Freezer, get's read from part.cfg. - public int FreezerSize; - - [KSPField(isPersistant = true, guiActive = true, guiName = "Total Frozen Kerbals")] //WISOTT Total number of frozen kerbals, just a count of the list object. - public int TotalFrozen; - - [KSPField(isPersistant = true, guiActive = true, guiName = "Freezer Space")] //Total space available for storage. Set by Part.cfg file. - public int FreezerSpace; - - [KSPField(isPersistant = true)] - public bool IsCrewableWhenFull; //Set by part.cfg. Intended to set whether a kerbal can enter the part when the frozen storage is filled up. Especially important for the single kerbal part. - - [KSPField()] - public bool IsFreezeActive; - - [KSPField()] - public bool IsThawActive; - - [KSPField()] - public double StoredCharge; - - [KSPField(isPersistant = true)] - public Int32 ChargeRequired; //Set by part.cfg. Total EC value required for a complete freeze or thaw. - - [KSPField(isPersistant = true)] - public Int32 ChargeRate; //Set by part.cfg. EC draw per tick. - - - public ProtoCrewMember ActiveKerbal; - public string ToThawKerbal; - - public List StoredCrew; - - protected AudioSource hatch_lock; - protected AudioSource ice_freeze; - protected AudioSource machine_hum; - protected AudioSource ding_ding; - - public override void OnUpdate() - { - if ((Time.time - lastUpdate) > updatetnterval) - { - - lastUpdate = Time.time; - UpdateEvents(); - //StoredCrew = StoredCrew.Distinct().ToList(); - if (StoredCrew.Count > 0) - { - FrozenCrew = String.Join(",", StoredCrew.ToArray()); - } - } - } - - public void FixedUpdate() - { - - if (IsFreezeActive == true) - { - - if (!requireResource(vessel, "ElectricCharge", ChargeRate, false) == true) - { - - ScreenMessages.PostScreenMessage("Insufficient electric charge to freeze kerbal.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - FreezeKerbalAbort(ActiveKerbal); - return; - } - else - { - requireResource(vessel, "ElectricCharge", ChargeRate, true); - StoredCharge = StoredCharge + ChargeRate; - //Debug.Log("Drawing Charge"); - if (StoredCharge > ChargeRequired) - { - if (requireResource(vessel, "Glykerol", 5, true)) - { - FreezeKerbalConfirm(ActiveKerbal); - } - else - { - - FreezeKerbalAbort(ActiveKerbal); - } - } - } - - } - if (IsThawActive == true) - { - if (!requireResource(vessel, "ElectricCharge", ChargeRate, false)) - { - ScreenMessages.PostScreenMessage("Insufficient electric charge to thaw kerbal.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - ThawKerbalAbort(ToThawKerbal); - } - else - { - requireResource(vessel, "ElectricCharge", ChargeRate, true); - StoredCharge = StoredCharge + ChargeRate; - if (StoredCharge > ChargeRequired) - { - ThawKerbalConfirm(ToThawKerbal); - } - } - } - } - - - public override void OnLoad(ConfigNode node) - { - //ChargeRequired = 3000; - //ChargeRate = 20; - Int32.TryParse(node.GetValue("ChargeRequired"), out ChargeRequired); - Int32.TryParse(node.GetValue("ChargeRate"), out ChargeRate); - IsCrewableWhenFull = Convert.ToBoolean(node.GetValue("IsCrewableWhenFull")); - FrozenCrew = node.GetValue("FrozenCrew"); - //Debug.Log(FrozenCrew); - LoadFrozenCrew(); - } - - public override void OnStart(PartModule.StartState state) - { - hatch_lock = gameObject.AddComponent(); - hatch_lock.clip = GameDatabase.Instance.GetAudioClip("PaladinLabs/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("PaladinLabs/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("PaladinLabs/DeepFreeze/Sounds/machine_hum"); - machine_hum.volume = .1F; - machine_hum.panLevel = 0; - machine_hum.rolloffMode = AudioRolloffMode.Linear; - machine_hum.Stop(); - ding_ding = gameObject.AddComponent(); - ding_ding.clip = GameDatabase.Instance.GetAudioClip("PaladinLabs/DeepFreeze/Sounds/ding_ding"); - ding_ding.volume = .25F; - ding_ding.panLevel = 0; - ding_ding.rolloffMode = AudioRolloffMode.Linear; - ding_ding.Stop(); - } - - public override void OnSave(ConfigNode node) - { - node.SetValue("FrozenCrew", FrozenCrew); - //Debug.Log("OnSave: " + node); - } - public override void OnInactive() - { - //Debug.Log("OnInactive" + FrozenCrew); - part.CrewCapacity = StoredCrew.Count; - foreach (var crewmember in StoredCrew) - { - - foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) - { - if (kerbal.name == crewmember) - part.AddCrewmember(kerbal); - } - - } - } - - private void LoadFrozenCrew() //The FrozenCrew variable is a string, we need it split into a list. - { - if (!string.IsNullOrEmpty(FrozenCrew)) - { - StoredCrew = FrozenCrew.Split(',').ToList(); - } - } - - private void UpdateEvents() - { - UpdateCounts(); - Events.Clear(); - if (!IsThawActive && !IsFreezeActive) - { - if (StoredCrew.Count < FreezerSize) - { - part.CrewCapacity = 1; - foreach (var CrewMember in part.protoModuleCrew) - { - Events.Add(new BaseEvent(Events, "Freeze " + CrewMember.name, () => - { - if ((FreezerSize - StoredCrew.Count) > 0 && part.protoModuleCrew.Contains(CrewMember)) - { - if (!requireResource(vessel, "Glykerol", 5, false)) - { - ScreenMessages.PostScreenMessage("Insufficient Glykerol to freeze kerbal.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - return; - } - else - { - FreezeKerbal(CrewMember); - //part.Events["Freeze " + CrewMember.name].guiActive = false; - } - } - - }, new KSPEvent { guiName = "Freeze " + CrewMember.name, guiActive = true })); - } - } - if ((part.protoModuleCrew.Count < part.CrewCapacity) || part.CrewCapacity <= 0) - foreach (var frozenkerbal in StoredCrew) - { - Events.Add(new BaseEvent(Events, "Thaw" + frozenkerbal, () => - { - if (StoredCrew.Contains(frozenkerbal)) - { - StoredCrew.Remove(frozenkerbal); - ToThawKerbal = frozenkerbal; - IsThawActive = true; - hatch_lock.Play(); - machine_hum.Play(); - machine_hum.loop = true; - } - - }, new KSPEvent { guiName = "Thaw " + frozenkerbal, guiActive = true })); - } - } - if (StoredCrew.Count >= FreezerSize && IsCrewableWhenFull == true) - { - part.CrewCapacity = 0; - } - - } - public void FreezeKerbal(ProtoCrewMember CrewMember) - { - - //Debug.Log("Freeze kerbal called"); - part.CrewCapacity = 0; - part.RemoveCrewmember(CrewMember); - ActiveKerbal = CrewMember; - IsFreezeActive = true; - ScreenMessages.PostScreenMessage("Starting Freeze", 5.0f, ScreenMessageStyle.UPPER_CENTER); - //Debug.Log("FrozenCrew =" + FrozenCrew); - UpdateCounts(); - Events.Clear(); - hatch_lock.Play(); - machine_hum.Play(); - machine_hum.loop = true; - } - - public void FreezeKerbalAbort(ProtoCrewMember kerbal) - { - - ScreenMessages.PostScreenMessage("Freezing Aborted", 5.0f, ScreenMessageStyle.UPPER_CENTER); - part.CrewCapacity = 1; - part.AddCrewmember(kerbal); - IsFreezeActive = false; - ActiveKerbal = null; - machine_hum.Stop(); - - } - public void ThawKerbalAbort(String ThawKerbal) - { - ScreenMessages.PostScreenMessage("Thawing Aborted", 5.0f, ScreenMessageStyle.UPPER_CENTER); - IsThawActive = false; - StoredCrew.Add(ThawKerbal); - StoredCharge = 0; - machine_hum.Stop(); - } - public void FreezeKerbalConfirm(ProtoCrewMember kerbal) - { - machine_hum.Stop(); - StoredCharge = 0; - StoredCrew.Add(kerbal.name); - StoredCrew = StoredCrew.Distinct().ToList(); - kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; - UpdateCounts(); - IsFreezeActive = false; - ActiveKerbal = null; - ScreenMessages.PostScreenMessage(kerbal.name + " frozen", 5.0f, ScreenMessageStyle.UPPER_CENTER); - ice_freeze.Play(); - - } - public void ThawKerbalConfirm(String frozenkerbal) - { - foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) //There's probably a more efficient way to find Protocrewmember from the CrewRoster - { - if (kerbal.name == frozenkerbal) - { - machine_hum.Stop(); - StoredCharge = 0; - part.CrewCapacity = 1; - part.AddCrewmember(kerbal); - ScreenMessages.PostScreenMessage(kerbal.name + " thawed out.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - //Debug.Log(StoredCrew.Remove(kerbal.name)); - ToThawKerbal = null; - IsThawActive = false; - - FrozenCrew = String.Join(",", StoredCrew.ToArray()); - //Debug.Log("FrozenCrew =" + FrozenCrew); - UpdateCounts(); - Events.Clear(); - ding_ding.Play(); - - } - } - } - // Simple bool for resource checking and usage. Returns true and optionally uses resource if resAmount of res is available. - Credit TMarkos https://github.com/TMarkos/ as this is lifted verbatim from his Beacon's pack. Mad modify as needed. - public bool requireResource(Vessel craft, string res, double resAmount, bool consumeResource) - { - if (!craft.loaded) return false; // Unloaded resource checking is unreliable. - Dictionary toDraw = new Dictionary(); - double resRemaining = resAmount; - foreach (Part cPart in craft.Parts) - { - foreach (PartResource cRes in cPart.Resources) - { - if (cRes.resourceName != res) continue; - if (cRes.amount == 0) continue; - if (cRes.amount >= resRemaining) - { - toDraw.Add(cRes, resRemaining); - resRemaining = 0; - } - else - { - toDraw.Add(cRes, cRes.amount); - resRemaining -= cRes.amount; - } - } - if (resRemaining <= 0) break; - } - if (resRemaining > 0) return false; - if (consumeResource) - { - foreach (KeyValuePair drawSource in toDraw) - { - drawSource.Key.amount -= drawSource.Value; - } - } - return true; - } - public void UpdateCounts() - { - FreezerSpace = (FreezerSize - StoredCrew.Count); - TotalFrozen = StoredCrew.Count; - } - - - - } - -} diff --git a/Source/DeepFreezerPart.cs b/Source/DeepFreezerPart.cs new file mode 100644 index 0000000..b72187d --- /dev/null +++ b/Source/DeepFreezerPart.cs @@ -0,0 +1,4678 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using DeepFreeze; +using RSTUtils; +using UnityEngine; +using Object = System.Object; +using Random = System.Random; +using KSP.Localization; +using KSP.UI.Screens.Flight; + +namespace DF +{ + [KSPModule("DeepFreeze Freezer Part")] + public class DeepFreezer : PartModule, IResourceConsumer + { + private float lastUpdate; // time since we last updated the part menu + private float lastRemove; // time since we last removed a part menu event + private float updatetnterval = .5f; // time between part menu updates + internal static float updateECTempInterval = 2f; // time between EC and Temp checks updates + internal double deathCounter; // time delay counter until the chance of a frozen kerbal dying due to lack of EC + internal double tmpdeathCounter; // time delay counter until the chance of a frozen kerbal dying due to part being too hot + internal static float tmpdeathRoll = 120f; // time delay until the chance of a frozen kerbal dying due to part being too hot + internal static float deathRoll = 240f; // time delay until the chance of a frozen kerbal dying due to lack of EC + internal double timeLoadedOffrails; // time the vessel this part is attached to was loaded or came off rails. + private Transform External_Window_Occluder; + private Renderer External_Window_Occluder_Renderer; + private Transform CRY_0300_Doors_Occluder; + private Shader depthMaskShader; + private Material External_Window_Material_Depth; + private Material External_Window_Material_Ice; + private Animation External_Window_Occluder_Anim; + + // EC and Temp Functions Vars + private Random rnd = new Random(); // Random seed for Killing Kerbals when we run out of EC to keep the Freezer running. + + private double heatamtMonitoringFrznKerbals = 5f; //amount of heat generated when monitoring a frozen kerbal, can by overridden by DeepFreeze master settings + private double heatamtThawFreezeKerbal = 50f; //amount of heat generated when freezing or thawing a kerbal, can be overriddent by DeepFreeze master settings + + #region Crew Transfer Vars + + public bool DFIcrewXferTOActive // Interface var for API = true if a Stock crewXfer to this part is active + { + get { return CrewHatchController.fetch.Active; } + } + public bool DFIcrewXferFROMActive // Interface var for API = true if a Stock crewXfer from this part is active + { + get { return CrewHatchController.fetch.Active; } + } + private bool crewTransferInputLock = false; //This is turned on if a stock Xfer is started and Off when it finishes. + private List CrewMoveList = new List(); //Store temp list of Parts in Stock Crew Transfer. + #endregion + + internal static ScreenMessage OnGoingECMsg, TempChkMsg; // used for the bottom right screen messages, these ones are static because the background processor uses them. + internal ScreenMessage ThawMsg, FreezeMsg, IVAKerbalName, IVAkerbalPart, IVAkerbalPod; // used for the bottom right screen messages + + private bool RTlastKerbalFreezeWarn; // set to true if you are using RemoteTech and you attempt to freeze your last kerbal in active vessel + + [KSPField(isPersistant = true, guiActive = false, guiName = "Animated")] //Set to true if Internal contains Animated Cryopods, read from part.cfg. + public bool isPartAnimated; + + [KSPField(isPersistant = true, guiActive = false, guiName = "PodExternal")] //Set to true if Cryopod is External part (eg. CRY-0300R), read from part.cfg. + public bool isPodExternal = false; + + [KSPField(isPersistant = true, guiActive = true, guiName = "#autoLOC_DF_00054")] //Total Size of Freezer, get's read from part.cfg. #autoLOC_DF_00054 = Freezer Capacity + public int FreezerSize; + + private CryopodEvents cryopodEvents; + + private class CryopodVariables + { + public string podName; + public Animation podAnimation; + public string windowName; + public string camName; + public Renderer extwindowRenderer; + public Renderer intwindowRenderer; + public Animation windowAnimation; + public Animation extwindowAnimation; + public string stripName; + public Animation stripAnimation; + public Camera camera; + } + private List cryopodVariables; + + #region API Vars + public int DFIFreezerSize + { + get + { + return FreezerSize; + } + } + + [KSPField(isPersistant = true, guiActive = true, guiName = "#autoLOC_DF_00055")] //WISOTT Total number of frozen kerbals, just a count of the list object. #autoLOC_DF_00055 = Total Frozen Kerbals + public int TotalFrozen; + + public int DFITotalFrozen + { + get + { + return TotalFrozen; + } + } + + [KSPField(isPersistant = true, guiActive = true, guiName = "#autoLOC_DF_00056")] //Total space available for storage. Set by Part.cfg file. #autoLOC_DF_00056 = Freezer Space + public int FreezerSpace; + + public int DFIFreezerSpace + { + get + { + return FreezerSpace; + } + } + + [KSPField(isPersistant = true, guiActive = true, guiName = "#autoLOC_DF_00057")] //Is set to true if the part is full (taking into account frozen kerbals in the part). #autoLOC_DF_00057 = Part is Full? + public bool PartFull; + + public bool DFIPartFull + { + get + { + return PartFull; + } + } + + public bool DFIECReqd + { + get { return DeepFreeze.Instance.DFsettings.ECreqdForFreezer; } + } + + [KSPField(isPersistant = false, guiName = "#autoLOC_DF_00058", guiActive = false)] //#autoLOC_DF_00058 = R/T Connection + public bool isRTConnected; + + [KSPField(isPersistant = true, guiName = "#autoLOC_DF_00059", guiActive = true)] //#autoLOC_DF_00059 = Freezer Temp + public FrzrTmpStatus _FrzrTmp = FrzrTmpStatus.OK; // ok, warning and red alert flags for temperature monitoring of the freezer + + public FrzrTmpStatus DFIFrzrTmp // Interface var for API = ok, warning and red alert flags for temperature monitoring of the freezer + { + get + { + return _FrzrTmp; + } + } + + internal FrzrTmpStatus DFFrzrTmp + { + get + { + return _FrzrTmp; + } + set + { + _FrzrTmp = value; + } + } + + [KSPField(isPersistant = true, guiName = "#autoLOC_DF_00060", guiUnits = "#autoLOC_DF_00061", guiFormat = "F1", guiActive = true)] //#autoLOC_DF_00060 = Cabin Temerature #autoLOC_DF_00061 = K + public float CabinTemp; + #endregion + + [KSPEvent(active = true, guiActive = true, name = "showMenu", guiName = "#autoLOC_DF_00062")] //#autoLOC_DF_00062 = DeepFreeze Menu + public void showMenu() + { + DeepFreezeGUI obj = DeepFreeze.Instance.GetComponent("DeepFreezeGUI") as DeepFreezeGUI; + if (obj != null) + obj.DFMenuAppLToolBar.GuiVisible = !obj.DFMenuAppLToolBar.GuiVisible; + else + Utilities.Log("DeepFreezer ToggleMenu error"); + } + + [KSPField(isPersistant = true)] + public float timeSinceLastECtaken; //This is the game time since EC was taken, for the ongoing EC usage while kerbal's are frozen + + [KSPField(isPersistant = true)] + public float timeSinceLastTmpChk; //This is the game time since Temperature was checked, for the ongoing storage of frozen kerbal's + + [KSPField(isPersistant = true, guiName = "Freezer Out of EC", guiActive = true)] + public bool _FreezerOutofEC; // true if the freezer has run out of EC + + public bool DFIFreezerOutofEC // Interface var for API = true if the freezer has run out of EC + { + get + { + return _FreezerOutofEC; + } + } + + internal bool DFFreezerOutofEC + { + get + { + return _FreezerOutofEC; + } + set + { + _FreezerOutofEC = value; + } + } + + [KSPField(isPersistant = false, guiName = "#autoLOC_DF_00063", guiUnits = "#autoLOC_DF_00064", guiActive = true)] //#autoLOC_DF_00063 = EC p/Kerbal to run #autoLOC_DF_00064 = \u0020p/min + public Int32 FrznChargeRequired; //Set by part.cfg. Total EC value required to maintain a frozen kerbal per minute. + + public Int32 DFIFrznChargeRequired + { + get + { + return FrznChargeRequired; + } + } + + [KSPField(isPersistant = false, guiActive = true, guiName = "#autoLOC_DF_00065", guiUnits = "#autoLOC_DF_00066", guiFormat = "F3")] //#autoLOC_DF_00065 = Current EC Usage #autoLOC_DF_00066 = \u0020p/sec + public float FrznChargeUsage; + + public float DFIFrznChargeUsage + { + get + { + return FrznChargeUsage; + } + } + + [KSPField(isPersistant = false, guiName = "#autoLOC_DF_00067", guiActive = true)] //#autoLOC_DF_00067 = Glykerol Reqd. to Freeze + public Int32 GlykerolRequired; //Set by part.cfg. Total Glykerol value required to freeze a kerbal. + + [KSPField] // set to active while freezing a kerbal + public bool IsFreezeActive; + + public bool DFIIsFreezeActive + { + get + { + return IsFreezeActive; + } + } + + [KSPField] // set to active while thawing a kerbal + public bool IsThawActive; + + public bool DFIIsThawActive + { + get + { + return IsThawActive; + } + } + + [KSPField] + public double StoredCharge; // Stores up EC as we are freezing or thawing over time until we reach what we need. + + [KSPField(isPersistant = false, guiName = "#autoLOC_DF_00068", guiActive = true)] //#autoLOC_DF_00068 = EC p/Kerbal to Frze/Thaw + public Int32 ChargeRequired; //Set by part.cfg. Total EC value required for a complete freeze or thaw. + + [KSPField(isPersistant = false)] + public Int32 ChargeRate; //Set by part.cfg. EC draw per tick. + + [KSPField] + public string animationName = string.Empty; //Set by part.cfg. name of external animation name for doors if equipped. + + [KSPField] + public bool PartHasDoor = false; //Set by part.cfg. true if part has external door (CRY-0300). + + private Animation externalDoorAnim; + private Animation externalDoorAnimOccluder; + + [KSPField(isPersistant = true)] + public bool ExternalDoorActive; //Set internal to partmodule. True if PartHasDoor and RPM/JSI TransparentPods is installed. Otherwise it is false. Used to determine if the door is activated/enabled or not. + + //we persist the external door state in strings because KSP can't handle ENUMs + [KSPField(isPersistant = true)] + public string strexternaldoorstate = "CLOSED"; + + internal DoorState _externaldoorstate = DoorState.CLOSED; + + [KSPField(isPersistant = true)] + public string strprevexterndoorstate = "CLOSED"; + + internal DoorState _prevexterndoorstate = DoorState.CLOSED; + + internal string _prevRPMTransparentpodSetting = string.Empty; + + + + [KSPField] + public string transparentTransforms = string.Empty; //Set by part.cfg. contains list of transforms that should be transparent | separated. + + private bool hasJSITransparentPod; + private bool checkRPMPodTransparencySettingError = false; + private bool RPMPodOccluderProcessingError = false; + + [KSPEvent(active = false, guiActive = true, guiActiveUnfocused = true, guiActiveEditor = true, unfocusedRange = 5f, name = "eventOpenDoors", guiName = "Open Doors")] + public void eventOpenDoors() + { + Events["eventOpenDoors"].active = false; + Utilities.Log_Debug("eventOpenDoors triggered - open the bay doors Hal"); + try + { + Animation[] animators = part.internalModel.FindModelAnimators("DOORHandle"); + if (animators.Length > 0) + { + var anim = animators[0]; + anim["DOORHandle"].speed = float.MaxValue; + anim["DOORHandle"].normalizedTime = 0; + anim.Play("DOORHandle"); + } + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + ext_door.Play(); + } + catch (Exception ex) + { + Utilities.Log("Exception trying to run the Doorhandle animation"); + Utilities.Log("Err: " + ex); + } + CRY_0300_Doors_Occluder = Utilities.SetInternalDepthMask(part, true, "CRY_0300_Doors_Occluder", CRY_0300_Doors_Occluder); + StartCoroutine(openDoors(1f)); + } + + [KSPAction("OpenDoors")] + public void ActivateAction(KSPActionParam param) + { + eventOpenDoors(); + } + + [KSPEvent(active = false, guiActive = true, guiActiveUnfocused = true, guiActiveEditor = true, unfocusedRange = 5f, name = "eventCloseDoors", guiName = "Close Doors")] + public void eventCloseDoors() + { + Events["eventCloseDoors"].active = false; + Utilities.Log_Debug("eventOpenDoors triggered - close the bay doors Hal"); + try + { + Animation[] animators = part.internalModel.FindModelAnimators("DOORHandle"); + if (animators.Length > 0) + { + var anim = animators[0]; + anim["DOORHandle"].speed = float.MinValue; + anim["DOORHandle"].normalizedTime = 1; + anim.Play("DOORHandle"); + } + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + ext_door.Play(); + } + catch (Exception ex) + { + Utilities.Log("Exception trying to run the Doorhandle animation"); + Utilities.Log("Err: " + ex); + } + CRY_0300_Doors_Occluder = Utilities.SetInternalDepthMask(part, true, "CRY_0300_Doors_Occluder", CRY_0300_Doors_Occluder); + StartCoroutine(closeDoors(-1f)); + } + + [KSPAction("CloseDoors")] + public void DeActivateAction(KSPActionParam param) + { + eventCloseDoors(); + } + + [KSPField] + public string TransparentSpecularShaderName = "Legacy Shaders/Transparent/Diffuse"; + [KSPField] + public string DepthMaskShaderName = "DepthMask"; + [KSPField] + public string KSPSpecularShaderName = "KSP/Specular"; + // These vars store info about the kerbal while we are freezing or thawing + private ProtoCrewMember ActiveFrzKerbal; + + private string ToFrzeKerbal = ""; + private int ToFrzeKerbalSeat; + private string ToFrzeKerbalXformNme = "Unknown"; + private string ToThawKerbal = ""; + private int ToThawKerbalSeat; + private bool skipThawStep1; + private bool emergencyThawInProgress; + private bool OpenPodAnimPlaying; + private bool ClosePodAnimPlaying; + private bool ThawWindowAnimPlaying; + private bool FreezeWindowAnimPlaying; + private int ThawStepInProgress; + private int FreezeStepInProgress; + private Shader TransparentSpecularShader; + private Shader KSPSpecularShader; + private object JSITransparentPodModule; + private FieldInfo JSIATPtransparentPodSetting; + private string transparentPodSetting; + private bool IVAOverlaySetting; + + private FrznCrewList _StoredCrewList = new FrznCrewList(); // This is the frozen StoredCrewList for the part + + public FrznCrewList DFIStoredCrewList // Interface var for API = This is the frozen StoredCrewList for the part + { + get + { + return _StoredCrewList; + } + } + + //Various Vars about the part and the vessel it is attached to + private string Glykerol = "Glykerol"; + + private string EC = "ElectricCharge"; + private Guid CrntVslID; + private uint CrntPartID; + private string CrntVslName = ""; + private bool vesselisinIVA; + private bool vesselisinInternal; + private int internalSeatIdx; + + private bool setGameSettings; + + internal bool partHasInternals; + private bool partHasStripLights; + private bool onvslchgInternal; //set to true if a VesselChange game event is triggered by this module + private bool onvslchgExternal; //set to true if a VesselChange game event is triggered outside of this module + private bool onvslchgNotActive; //sets a timer count started when external VesselChange game event is triggered before resetting cryopod and extdoor animations. + private float onvslchgNotActiveDelay; // timer as per previous var + private double ResAvail; + private bool IsRTInstalled; + + [KSPField(isPersistant = true)] //we keep the game time the last cryopod reset occured here and only run if the last one was longer than cryopodResetTimeDelay ago. + private double cryopodResetTime; + + [KSPField(isPersistant = true)] //we persist the cryopod animation states in a string because KSP can't handle bool arrays + public string cryopodstateclosedstring; + + private bool[] cryopodstateclosed; //This bool array is set to true for each cryopod on the part when the cryopod is in closed state. + private bool[] seatTakenbyFrznKerbal; //This bool array is set to true for each seat that is currently being taken by a frozen kerbal. + + private EventData onATPPodSettingChanged; + + + #region Audio Vars + private AudioSource mon_beep; + private AudioSource flatline; + private AudioSource hatch_lock; + private AudioSource ice_freeze; + private AudioSource machine_hum; + private AudioSource ding_ding; + private AudioSource ext_door; + private AudioSource charge_up; + #endregion + + public override string GetInfo() + { + string text = string.Empty; + text += Localizer.Format("#autoLOC_DF_00069", FreezerSize); //#autoLOC_DF_00069 = \nCryopods: <<1>> + + return text; + } + + public List GetConsumedResources() + { + List resources = new List(); + PartResourceDefinition glykerol = PartResourceLibrary.Instance.GetDefinition(Glykerol); + resources.Add(glykerol); + PartResourceDefinition electricCharge = PartResourceLibrary.Instance.GetDefinition(EC); + resources.Add(electricCharge); + return resources; + } + + //This is called via reflection from JSIATP + public void InternalModelCreated() + { + SetCryopodVariables(); + SetIVAOccluders(); + } + + private void SetIVAOccluders() + { + if (animationName != string.Empty && PartHasDoor && externalDoorAnim != null) + { + if (part.internalModel != null) + { + externalDoorAnimOccluder = null; + var anims = part.internalModel.FindModelAnimators(animationName); + if (anims.Length > 0) + { + externalDoorAnimOccluder = anims[0]; + } + + if (externalDoorAnimOccluder != null) + { + if (externalDoorAnim != null && externalDoorAnim.IsPlaying(animationName)) + { + externalDoorAnimOccluder[animationName].normalizedTime = externalDoorAnim[animationName].normalizedTime; + externalDoorAnimOccluder[animationName].speed = externalDoorAnim[animationName].speed; + externalDoorAnimOccluder.Play(animationName); + } + } + } + else + { + externalDoorAnimOccluder = null; + Utilities.Log_Debug("No InternalModel found to check for external door occluder animation"); + } + } + } + + public void Update() + { + if (Time.timeSinceLevelLoad < 2.0f) // Check not loading level + return; + + // This should only happen once in flight only, we need to load the StoredCrewList of frozen kerbals for this part from the DeepFreeze master list + //This should be done in onload, but it doesn't seem to be working, probably should be checking and doing when vessel loads/unloads/switches/etc. + if (!setGameSettings && HighLogic.LoadedSceneIsFlight) + { + onceoffSetup(); + } + + //For some reason when we go on EVA or switch vessels the InternalModel is destroyed. + //Which causes a problem when we re-board the part as the re-boarding kerbal ends up in a frozen kerbals seat. + //So we check for the internalmodel existing while the vessel this part is attached to is loaded and if it isn't we re-instansiate it. + if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && vessel.loaded && partHasInternals && part.internalModel == null) + { + Utilities.Log("Part " + part.name + "(" + part.flightID + ") is loaded and internalModel has disappeared, so re-instantiate it"); + //part.SpawnIVA(); + Utilities.spawnInternal(part); + InternalModelCreated(); + resetFrozenKerbals(); + resetCryopods(true); + StartCoroutine(UnregisterPortraits()); + if (vesselisinInternal) + { + setIVAFrzrCam(internalSeatIdx); + } + } + + // If we have an external door (CRY-0300) or external pod (CRY-0300R) check RPM transparency setting and change the door settings as appropriate + if (PartHasDoor || isPodExternal) + { + //This is still here in case user is using an OLD version of JSIATP. The latest version will not run this and will be GameEvent Driven. + if (onATPPodSettingChanged == null && DFInstalledMods.IsJSITransparentPodsInstalled && !IsFreezeActive && !IsThawActive) + { + try + { + checkRPMPodTransparencySetting(); + } + catch (Exception ex) + { + Utilities.Log("Exception attempting to check RPM transparency settings. Report this error on the Forum Thread."); + Utilities.Log("Err: " + ex); + } + } + //We have to process the occluders + if (DFInstalledMods.IsJSITransparentPodsInstalled) + { + //This is still here in case user is using an OLD version of JSIATP. The latest version will not run this and will be GameEvent Driven. + if (onATPPodSettingChanged == null) + { + RPMPodOccluderProcessing(); + } + } + else + { + noRPMPodOccluderProcessing(); + } + } + + if (!HighLogic.LoadedSceneIsFlight) // If scene is not flight we are done with onUpdate + return; + + //We need to update transprency settings if the user toggles the stock overlay camera. There is no game event for this. + if (IVAOverlaySetting != Utilities.StockOverlayCamIsOn) + { + OnATPPodSettingChanged(this.part, transparentPodSetting); + IVAOverlaySetting = Utilities.StockOverlayCamIsOn; + } + + //This is necessary to override stock crew xfer behaviour. When the user cancels the xfer the Stock highlighting system + // it makes the transparent pod opaque. + // so when a Transfer dialog is started we set crewTranferInputLock to true. + // Here we check if it is true and the crewhatchcontroller is not active the user must have cancelled and we need + // to reset the pod to transparent. + // If they complete the transfer then the bool will be turned off by those gameevents and we don't have to reset the pod. + if (crewTransferInputLock && !CrewHatchController.fetch.Active) + { + crewTransferInputLock = false; //Reset the bool and then process. + if (FlightGlobals.ready && vessel.loaded && isPodExternal && !IsFreezeActive && !IsThawActive && DFInstalledMods.IsJSITransparentPodsInstalled) + { + if (_prevRPMTransparentpodSetting == "ON") + { + for (int i = 0; i < cryopodstateclosed.Length; i++) + { + if (!cryopodstateclosed[i]) //If there isn't a frozen kerbal inside + { + string windowname = "Cryopod-" + (i + 1) + "-Window"; + Renderer extwindowrenderer = part.FindModelComponent(windowname); + if (extwindowrenderer != null) + { + if (extwindowrenderer.material.shader != TransparentSpecularShader) + { + setCryopodWindowTransparent(i); + //External_Window_Occluder = Utilities.SetInternalDepthMask(part, false, "External_Window_Occluder", External_Window_Occluder); + } + } + } + } + } + } + } + + if (PartHasDoor && Utilities.IsInIVA) //So if we are in IVA mode (inside this loop) and in a CRY-0300 (have External door) Open the Kerbals EYES WIDER! + { + //Kerbal currentKerbal = CameraManager.Instance.IVACameraActiveKerbal; + CameraManager.Instance.IVACameraActiveKerbal.kerbalCam.nearClipPlane = 0.01f; + CameraManager.Instance.IVACameraActiveKerbal.kerbalCam.fieldOfView = 95f; + //CameraManager.Instance.ivaFOV = 95f; + //Turn OFF the Door occluders so we can see outside. + //if (_externaldoorstate != DoorState.OPEN) + //{ + // CRY_0300_Doors_Occluder = Utilities.SetInternalDepthMask(part, false, "CRY_0300_Doors_Occluder", CRY_0300_Doors_Occluder); + //} + } + + if (Time.time - lastUpdate > updatetnterval && Time.time - lastRemove > updatetnterval) // We only update every updateinterval time interval. + { + lastUpdate = Time.time; + if (FlightGlobals.ready && FlightGlobals.ActiveVessel != null) + { + CrntVslID = vessel.id; + CrntVslName = vessel.vesselName; + + //Set the Part temperature in the partmenu + if (DeepFreeze.Instance.DFsettings.TempinKelvin) + { + Fields["CabinTemp"].guiUnits = Localizer.Format("#autoLOC_DF_00061"); //#autoLOC_DF_00061 = K + CabinTemp = (float)part.temperature; + } + else + { + Fields["CabinTemp"].guiUnits = Localizer.Format("#autoLOC_DF_00070"); //#autoLOC_DF_00070 = C + CabinTemp = Utilities.KelvintoCelsius((float)part.temperature); + } + + // If RemoteTech installed set the connection status + if (IsRTInstalled) + { + try + { + if (DFInstalledMods.RTVesselConnected(part.vessel.id)) + { + isRTConnected = true; + } + else + { + isRTConnected = false; + } + } + catch (Exception ex) + { + Utilities.Log("Exception attempting to check RemoteTech vessel connections. Report this error on the Forum Thread."); + Utilities.Log("Err: " + ex); + isRTConnected = false; + } + } + + // If we have an external door (CRY-0300) check if the door state has changed and then set the helmet state + if (ExternalDoorActive) + { + // if the current and previous door states are different we need to do checks, otherwise we do nothing. + if (_externaldoorstate != _prevexterndoorstate) + { + // if the previous state was closing and now it's closed we can take our helmets off. + if (_prevexterndoorstate == DoorState.CLOSING || _externaldoorstate == DoorState.CLOSED) + { + part.setHelmets(false); + } + else // all other door states we keep our helmets on. + { + part.setHelmets(true); + } + _prevexterndoorstate = _externaldoorstate; + } + } + + //Refresh IVA mode Messages and Bools + if (IVAKerbalName != null) ScreenMessages.RemoveMessage(IVAKerbalName); + if (IVAkerbalPart != null) ScreenMessages.RemoveMessage(IVAkerbalPart); + if (IVAkerbalPod != null) ScreenMessages.RemoveMessage(IVAkerbalPod); + if (Utilities.VesselIsInIVA(part.vessel)) + { + // Utilities.Log_Debug("Vessel is in IVA mode"); + vesselisinIVA = true; + vesselisinInternal = false; + //Kerbal actkerbal = CameraManager.Instance.IVACameraActiveKerbal; + if (CameraManager.Instance.IVACameraActiveKerbal != null) + { + if (Utilities.ActiveKerbalIsLocal(part)) + { + ProtoCrewMember crew = null; + List.Enumerator enumerator = part.protoModuleCrew.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == CameraManager.Instance.IVACameraActiveKerbal.name) + crew = enumerator.Current; + } + int SeatIndx = -1; + if (crew != null) + { + SeatIndx = crew.seatIdx; + } + // Utilities.Log_Debug("ActiveKerbalFound, seatidx=" + SeatIndx); + if (SeatIndx != -1) + { + SeatIndx++; + IVAkerbalPod = new ScreenMessage(Localizer.Format("#autoLOC_DF_00071", SeatIndx), 1, ScreenMessageStyle.UPPER_LEFT); //#autoLOC_DF_00071 = Pod:<<1>> + IVAkerbalPod.color = Color.white; + ScreenMessages.PostScreenMessage(IVAkerbalPod); + } + IVAkerbalPart = new ScreenMessage(part.name.Substring(0, 8), 1, ScreenMessageStyle.UPPER_LEFT); + IVAkerbalPart.color = Color.white; + ScreenMessages.PostScreenMessage(IVAkerbalPart); + + IVAKerbalName = new ScreenMessage(CameraManager.Instance.IVACameraActiveKerbal.crewMemberName, 1, ScreenMessageStyle.UPPER_LEFT); + IVAKerbalName.color = Color.white; + ScreenMessages.PostScreenMessage(IVAKerbalName); + } + } + //monitoring beep + if (TotalFrozen > 0 && !mon_beep.isPlaying && DeepFreeze.Instance.DFsettings.BeepSoundsActive) + { + mon_beep.Play(); + } + } + else + { + if (IVAKerbalName != null) ScreenMessages.RemoveMessage(IVAKerbalName); + if (IVAkerbalPart != null) ScreenMessages.RemoveMessage(IVAkerbalPart); + if (IVAkerbalPod != null) ScreenMessages.RemoveMessage(IVAkerbalPod); + vesselisinIVA = false; + // Utilities.Log_Debug("Vessel is NOT in IVA mode"); + if (Utilities.IsActiveVessel(vessel) && Utilities.IsInInternal) + { + vesselisinInternal = true; + if (TotalFrozen > 0 && !mon_beep.isPlaying && DeepFreeze.Instance.DFsettings.BeepSoundsActive) + { + mon_beep.Play(); + } + // Utilities.Log_Debug("Vessel is in Internal mode"); + } + else + { + vesselisinInternal = false; + if (mon_beep.isPlaying) + { + mon_beep.Stop(); + } + // Utilities.Log_Debug("Vessel is NOT in Internal mode"); + } + } + } + } + //UpdateCounts(); // Update the Kerbal counters and stored crew lists for the part - MOVED to FixedUpdate + } + + private void checkRPMPodTransparencySetting() + { + try + { + //Only proceed if we have a TransparentPodPartModule. + if (JSITransparentPodModule != null && JSIATPtransparentPodSetting != null) + { + //Get the transparentPodSetting (ON/OFF/AUTO). + GetTransparentPodSetting(); + //We only need to do this processing if the Pod Setting has CHANGED since last time we checked. + if (transparentPodSetting != _prevRPMTransparentpodSetting) + { + if (PartHasDoor) //CRY-0300 + { + processRPMPodSettingsPartHasDoor(transparentPodSetting); + } + else + { + if (isPodExternal) //CRY-0300R + { + processRPMPodSettingsPodisExternal(transparentPodSetting); + } + } + _prevRPMTransparentpodSetting = transparentPodSetting; + } + } + } + catch (Exception ex) + { + if (!checkRPMPodTransparencySettingError) + { + Utilities.Log("DeepFreezer Error checking RPM TransparentPod Setting"); + Utilities.Log("DeepFreezer ", ex.Message); + checkRPMPodTransparencySettingError = true; + } + } + } + + private void processRPMPodSettingsPartHasDoor(string transparentPodSetting) + { + switch (transparentPodSetting) + { + case "ON": + // If the doors are closed or closing set open doors event active + if (_externaldoorstate != DoorState.CLOSED && + _externaldoorstate != DoorState.CLOSING) + { + Events["eventOpenDoors"].active = false; + Events["eventCloseDoors"].active = true; + } + else + { + //If the doors are open or opening set close doors event active + if (_externaldoorstate != DoorState.OPEN && + _externaldoorstate != DoorState.OPENING) + { + Events["eventOpenDoors"].active = true; + Events["eventCloseDoors"].active = false; + } + } + break; + + default: + Utilities.Log_Debug("RPM set to OFF or AUTO for transparent pod"); + + // We must close the doors if they are not or we see an empty internal. + DoorState actualDoorState = getdoorState(); + if (actualDoorState != DoorState.CLOSED) + { + try + { + //Animate the RPM Door Handle Prop + Animation anim; + Animation[] animators = + part.internalModel.FindModelAnimators("DOORHandle"); + if (animators.Length > 0) + { + anim = animators[0]; + anim["DOORHandle"].speed = float.MinValue; + anim["DOORHandle"].normalizedTime = 1; + anim.Play("DOORHandle"); + } + //ext_door.Play(); + } + catch (Exception ex) + { + Debug.Log("Exception trying to run the Doorhandle animation"); + Debug.Log("Err: " + ex); + } + + //Run the Close Door Animation. + if (animationName != null) + { + if (externalDoorAnimOccluder != null) + { + externalDoorAnimOccluder[animationName].normalizedTime = 1; + externalDoorAnimOccluder[animationName].speed = float.MinValue; + externalDoorAnimOccluder.Play(animationName); + } + externalDoorAnim[animationName].normalizedTime = 1; + externalDoorAnim[animationName].speed = float.MinValue; + externalDoorAnim.Play(animationName); + } + _prevexterndoorstate = _externaldoorstate; + _externaldoorstate = DoorState.CLOSED; + } + Events["eventOpenDoors"].active = false; + Events["eventCloseDoors"].active = false; + + break; + } + } + + private void processRPMPodSettingsPodisExternal(string transparentPodSetting) + { + switch (transparentPodSetting) + { + case "ON": + + for (int i = 0; i < cryopodVariables.Count; i++) + { + Renderer extwindowrenderer = cryopodVariables[i].extwindowRenderer; + if (extwindowrenderer != null) + { + + if (HighLogic.LoadedSceneIsFlight) + //If in flight, we check the pod state + { + if (!cryopodstateclosed[i]) //No frozen kerbal inside + { + if (extwindowrenderer.material.shader != TransparentSpecularShader) + { + setCryopodWindowTransparent(i); + } + } + else //Frozen kerbal inside + { + if (extwindowrenderer.material.shader != KSPSpecularShader) + { + setCryopodWindowSpecular(i); + } + } + } + else //If in editor, always transparent + { + if (extwindowrenderer.material.shader != TransparentSpecularShader) + { + setCryopodWindowTransparent(i); + } + } + } + } + break; + + default: + Utilities.Log_Debug("RPM set to OFF or AUTO for transparent pod"); + + for (int i = 0; i < cryopodVariables.Count; i++) + { + Renderer extwindowrenderer = cryopodVariables[i].extwindowRenderer; + if (extwindowrenderer != null) + { + if (extwindowrenderer.material.shader != KSPSpecularShader) + { + setCryopodWindowSpecular(i); + } + } + } + break; + } + } + + private void RPMPodOccluderProcessing() + { + try + { + //We have to process the occluders for the CRY-0300 and CRY-0300R for KSP 1.1 + if (HighLogic.LoadedSceneIsFlight && !Utilities.IsInIVA) + { + //Only proceed if we have a TransparentPodPartModule. + if (JSITransparentPodModule != null && JSIATPtransparentPodSetting != null) + { + //Get the transparentPodSetting (ON/OFF/AUTO). + GetTransparentPodSetting(); + if (PartHasDoor) //If CRY-0300, set the door occluder ON so we see the doors + { + //If Stock Overlay is on we turn the Occluder OFF so we can see inside. + //Otherwise we see the closed/closing/opening doors. + if (Utilities.StockOverlayCamIsOn) + { + CRY_0300_Doors_Occluder = Utilities.SetInternalDepthMask(part, false, "CRY_0300_Doors_Occluder", CRY_0300_Doors_Occluder); + } + else + { + CRY_0300_Doors_Occluder = Utilities.SetInternalDepthMask(part, true, "CRY_0300_Doors_Occluder", CRY_0300_Doors_Occluder); + } + } + else if (isPodExternal) //CRY-0300R + { + //The CRY-0300R is a bit backwards. Occluders when ON will SHOW the external part. + //So in the case of the CRY-0300R we want to SHOW the external PART when there is a frozen Kerbal only. + //But don't cycle the Occluder if a freeze or thaw is running otherwise we interrupt the nice freeze/thaw + //effect on the window glass. + if (IsThawActive || IsFreezeActive) + return; + if (!cryopodstateclosed[0] && transparentPodSetting == "ON") //No frozen kerbal inside + { + External_Window_Occluder = Utilities.SetInternalDepthMask(part, false, "External_Window_Occluder", External_Window_Occluder); + } + else //Frozen kerbal inside or OFF or AUTO model. + { + External_Window_Occluder = Utilities.SetInternalDepthMask(part, true, "External_Window_Occluder", External_Window_Occluder); + } + } + } + } + } + catch (Exception ex) + { + if (!RPMPodOccluderProcessingError) + { + Utilities.Log("DeepFreezer Error setting RPM Occluders"); + Utilities.Log("DeepFreezer ", ex.Message); + RPMPodOccluderProcessingError = true; + } + } + } + + private void noRPMPodOccluderProcessing() + { + try + { + //If RPM is not installed we need to set the depthshader occluders for the stock overlay processing. + //We have to process the occluders for the CRY-0300 and CRY-0300R for KSP 1.1 + if (HighLogic.LoadedSceneIsFlight && !Utilities.IsInIVA) + { + if (PartHasDoor) //If CRY-0300, set the door occluder ON so we see the closed/closing doors + { + //If Stock Overlay is on we turn the Occluder OFF so we can see inside. + //Otherwise is it ON. + if (Utilities.StockOverlayCamIsOn) + { + CRY_0300_Doors_Occluder = Utilities.SetInternalDepthMask(part, false, "CRY_0300_Doors_Occluder", CRY_0300_Doors_Occluder); + } + else + { + CRY_0300_Doors_Occluder = Utilities.SetInternalDepthMask(part, true, "CRY_0300_Doors_Occluder", CRY_0300_Doors_Occluder); + } + } + else if (isPodExternal) //CRY-0300R + { + //The CRY-0300R is a bit backwards. Occluders when ON will SHOW the external part. + //So in the case of the CRY-0300R we want to SHOW the external PART when there is a frozen Kerbal only. + //But don't cycle the Occluder if a freeze or thaw is running otherwise we interrupt the nice freeze/thaw + //effect on the window glass. + + if (!cryopodstateclosed[0] && (!IsThawActive || !IsFreezeActive)) //No frozen kerbal inside + { + External_Window_Occluder = Utilities.SetInternalDepthMask(part, false, "External_Window_Occluder", External_Window_Occluder); + + } + else //Frozen kerbal inside or freeze/thaw occuring. Can't see inside. + { + External_Window_Occluder = Utilities.SetInternalDepthMask(part, true, "External_Window_Occluder", External_Window_Occluder); + } + } + } + } + catch (Exception) + { + Utilities.Log("DeepFreezer Error setting no RPM Occluders"); + //Utilities.Log("DeepFreezer ", ex.Message); + } + } + + private void onceoffSetup() + { + Utilities.Log_Debug("DeepFreezer OnUpdate onceoffSetup"); + _StoredCrewList.Clear(); + CrntVslID = vessel.id; + CrntVslName = vessel.vesselName; + CrntPartID = part.flightID; + lastUpdate = Time.time; + lastRemove = Time.time; + if (DeepFreeze.Instance == null) + { + Utilities.Log("DeepFreezer Onceoffsetup - waiting for DeepFreeze settings instance"); + setGameSettings = false; + return; + } + + if (DFInstalledMods.IsJSITransparentPodsInstalled && part.Modules.Contains("JSIAdvTransparentPod")) + { + JSITransparentPodModule = part.Modules["JSIAdvTransparentPod"]; + JSIATPtransparentPodSetting = Utilities.GetFieldObject(JSITransparentPodModule, "transparentPodSetting"); + GetTransparentPodSetting(); + } + + // Master settings values override the part values for EC required and Glykerol required + if (DeepFreeze.Instance.DFsettings.ECReqdToFreezeThaw != ChargeRequired) + { + ChargeRequired = DeepFreeze.Instance.DFsettings.ECReqdToFreezeThaw; + } + if (DeepFreeze.Instance.DFsettings.GlykerolReqdToFreeze != GlykerolRequired) + { + GlykerolRequired = DeepFreeze.Instance.DFsettings.GlykerolReqdToFreeze; + } + if (DeepFreeze.Instance.DFsettings.RegTempReqd) + { + heatamtMonitoringFrznKerbals = DeepFreeze.Instance.DFsettings.heatamtMonitoringFrznKerbals; + heatamtThawFreezeKerbal = DeepFreeze.Instance.DFsettings.heatamtThawFreezeKerbal; + } + PartInfo partInfo; + if (DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(part.flightID, out partInfo)) + { + timeSinceLastECtaken = (float)partInfo.timeLastElectricity; + timeSinceLastTmpChk = (float)partInfo.timeLastTempCheck; + } + Utilities.Log_Debug("DeepFreezer This CrntVslID = " + CrntVslID + " This CrntPartID = " + CrntPartID + " This CrntVslName = " + CrntVslName); + + // Set a flag if this part has internals or not. If it doesn't we don't try to save/restore specific seats for the frozen kerbals + if (part.partInfo.internalConfig.HasData) + { + partHasInternals = true; + } + else + { + partHasInternals = false; + } + //For some reason when we go on EVA or switch vessels the InternalModel is destroyed. + //Which causes a problem when we re-board the part as the re-boarding kerbal ends up in a frozen kerbals seat. + //So we check for the internalmodel existing while the vessel this part is attached to is loaded and if it isn't we re-instansiate it. + if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && vessel.loaded && partHasInternals && part.internalModel == null) + { + Utilities.Log("Part " + part.name + "(" + part.flightID + ") is loaded and internalModel has disappeared, so re-instantiate it"); + Utilities.spawnInternal(part); + StartCoroutine(UnregisterPortraits()); + } + + resetFrozenKerbals(); + + Utilities.Log_Debug("Onceoffsetup resetcryopod doors"); + if (partHasInternals) + { + resetCryopods(true); + } + + //For all thawed crew in part, change their IVA animations to be less well.. animated? + foreach (ProtoCrewMember crew in part.protoModuleCrew) + { + if (crew.KerbalRef != null) + { + Utilities.subdueIVAKerbalAnimations(crew.KerbalRef); + } + } + + //If we have an external door (CRY-0300) enabled set the current door state and the helmet states + if (ExternalDoorActive) + { + setHelmetstoDoorState(); + } + //If we have lightstrips (CRY-5000) set them up + if (partHasInternals) + { + try + { + Animation[] animators = part.internalModel.FindModelAnimators("LightStrip"); + if (animators.Length > 0) + { + Utilities.Log_Debug("Found " + animators.Length + " LightStrip animations starting"); + partHasStripLights = true; + if (DeepFreeze.Instance.DFsettings.StripLightsActive) + { + foreach (Animation anim in animators) + { + anim["LightStrip"].speed = 1; + anim["LightStrip"].normalizedTime = 0; + anim.wrapMode = WrapMode.Loop; + anim.Play("LightStrip"); + } + } + else + { + foreach (Animation anim in animators) + { + anim.Stop(); + } + } + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreezer Error finding Internal LightStrip Animators"); + Utilities.Log(ex.Message); + } + } + cryopodEvents = new CryopodEvents(part, this); + cryopodEvents.SyncEvents(); + OnATPPodSettingChanged(this.part, transparentPodSetting); + IVAOverlaySetting = Utilities.StockOverlayCamIsOn; + setGameSettings = true; //set the flag so this method doesn't execute a second time + } + + private void GetTransparentPodSetting() + { + if (JSIATPtransparentPodSetting != null) + { + transparentPodSetting = JSIATPtransparentPodSetting.GetValue(JSITransparentPodModule).ToString(); + } + } + + private void FixedUpdate() + { + if (Time.timeSinceLevelLoad < 2.0f || !setGameSettings) // Check not loading level + { + return; + } + + if (IsFreezeActive) // Process active freezing process + { + ProcessFreezeKerbal(); + } + + if (IsThawActive) // Process active thawing process + { + ProcessThawKerbal(); + } + + //If an emergency thaw has been called, thaw the first kerbal in the stored frozen kerbal list until none remain. + if (!IsFreezeActive && !IsThawActive && emergencyThawInProgress && vessel.isActiveVessel) + { + if (_StoredCrewList.Count > 0) + { + skipThawStep1 = true; // we don't use any EC for emergency thaw + beginThawKerbal(_StoredCrewList[0].CrewName); + } + else + { + Utilities.Log_Debug("Emergency Thaw completed"); + } + } + + // The following section is the on-going EC check and temperature checks and update the seat counts for the freezer, only in flight and activevessel + if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && vessel.isActiveVessel && setGameSettings) + { + if (DeepFreeze.Instance.DFsettings.ECreqdForFreezer) + { + Fields["FrznChargeRequired"].guiActive = true; + Fields["FrznChargeUsage"].guiActive = true; + Fields["_FreezerOutofEC"].guiActive = true; + if (Utilities.timewarpIsValid(5)) // EC usage and generation still seems to work up to warpfactor of 4. + { + PartInfo partInfo; + if (!DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(part.flightID, out partInfo)) + { + Utilities.Log("Freezer Part NOT found: " + part.name + "(" + part.flightID + ")" + " (" + vessel.id + ")"); + partInfo = new PartInfo(vessel.id, part.name, Planetarium.GetUniversalTime()); + partInfo.ECWarning = false; + } + ChkOngoingEC(partInfo); // Check the on-going EC usage + } + else + { + timeSinceLastECtaken = (float)Planetarium.GetUniversalTime(); + } + } + else + { + Fields["FrznChargeRequired"].guiActive = false; + Fields["FrznChargeUsage"].guiActive = false; + Fields["_FreezerOutofEC"].guiActive = false; + timeSinceLastECtaken = (float)Planetarium.GetUniversalTime(); + } + + if (DeepFreeze.Instance.DFsettings.RegTempReqd) + { + Fields["_FrzrTmp"].guiActive = true; + if (Utilities.timewarpIsValid(2)) // Temperature is buggy in timewarp so it is disabled whenever timewarp is on. + { + PartInfo partInfo; + if (!DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(part.flightID, out partInfo)) + { + Utilities.Log("Freezer Part NOT found: " + part.name + "(" + part.flightID + ")" + " (" + vessel.id + ")"); + partInfo = new PartInfo(vessel.id, part.name, Planetarium.GetUniversalTime()); + partInfo.TempWarning = false; + } + ChkOngoingTemp(partInfo); // Check the on-going Temperature + } + else + { + timeSinceLastTmpChk = (float)Planetarium.GetUniversalTime(); + } + } + else + { + Fields["_FrzrTmp"].guiActive = false; + } + + UpdateCounts(); // Update the Kerbal counters and stored crew lists for the part + } + } + + private void ChkOngoingEC(PartInfo partInfo) + { + // The following section of code consumes EC when we have ECreqdForFreezer set to true in the part config. + // This consumes electric charge when we have frozen kerbals on board. + // But due to bugs in KSP ith EC and SolarPanels at high timewarp if timewarp is > 4x we turn it off. + // If we run out of EC and Lethal setting is on, we roll the dice. There is a 1 in 3 chance a Kerbal will DIE!!!! + // If lethal setting is off an emergency thaw of all frozen crew occurs. + + //Utilities.Log_Debug("ChkOngoingEC start"); + double currenttime = Planetarium.GetUniversalTime(); + double timeperiod = currenttime - timeSinceLastECtaken; + // Utilities.Log_Debug("currenttime = " + currenttime + " timeperiod = " + timeperiod + " updateECTempInterval= " + updateECTempInterval); + if (timeperiod > updateECTempInterval) //only update every updateECTempInterval to avoid request resource bug when amounts are too small + { + if (TotalFrozen > 0 && !CheatOptions.InfiniteElectricity) //We have frozen Kerbals, consume EC + { + double ECreqd = FrznChargeRequired / 60.0f * timeperiod * TotalFrozen; + Utilities.Log_Debug("DeepFreezer Running the freezer parms currenttime = {0} timeperiod = {1} ecreqd = {2}" , currenttime.ToString(), timeperiod.ToString(), ECreqd.ToString()); + double resTotal = 0f; + if (Utilities.requireResource(vessel, EC, ECreqd, false, true, false, out ResAvail, out resTotal)) + { + if (OnGoingECMsg != null) ScreenMessages.RemoveMessage(OnGoingECMsg); + //Have resource + Utilities.requireResource(vessel, EC, ECreqd, true, true, false, out ResAvail, out resTotal); + FrznChargeUsage = (float)ResAvail; + Utilities.Log_Debug("DeepFreezer Consumed Freezer EC " + ECreqd + " units"); + timeSinceLastECtaken = (float)currenttime; + deathCounter = currenttime; + _FreezerOutofEC = false; + partInfo.ECWarning = false; + } + else + { + if (currenttime - timeLoadedOffrails < 5.0f) // this is true if vessel just loaded or we just switched to this vessel or vessel just came off rails + // we need to check if we aren't going to exhaust all EC in one call.. and??? + { + ECreqd = resTotal * 95 / 100; + double ECtotal = 0f; + if (Utilities.requireResource(vessel, EC, ECreqd, false, true, false, out ResAvail, out resTotal)) + { + Utilities.requireResource(vessel, EC, ECreqd, true, true, false, out ResAvail, out resTotal); + FrznChargeUsage = (float)ResAvail; + timeSinceLastECtaken = (float)currenttime; + deathCounter = currenttime; + } + } + //Debug.Log("DeepFreezer Ran out of EC to run the freezer"); + if (!partInfo.ECWarning) + { + if (TimeWarp.CurrentRateIndex > 1) Utilities.stopWarp(); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00072"), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00072 = Insufficient electric charge to monitor frozen kerbals. + partInfo.ECWarning = true; + deathCounter = currenttime; + } + if (OnGoingECMsg != null) ScreenMessages.RemoveMessage(OnGoingECMsg); + OnGoingECMsg = ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00073", (deathRoll - (currenttime - deathCounter)).ToString("######0"))); //#autoLOC_DF_00073 = \u0020Freezer Out of EC : Systems critical in <<1>> secs + _FreezerOutofEC = true; + FrznChargeUsage = 0f; + Utilities.Log_Debug("DeepFreezer deathCounter = " + deathCounter); + if (currenttime - deathCounter > deathRoll) + { + if (DeepFreeze.Instance.DFsettings.fatalOption) + { + Utilities.Log_Debug("DeepFreezer deathRoll reached, Kerbals all die..."); + deathCounter = currenttime; + //all kerbals die + var kerbalsToDelete = new List(); + foreach (FrznCrewMbr deathKerbal in _StoredCrewList) + { + DeepFreeze.Instance.KillFrozenCrew(deathKerbal.CrewName); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00074", deathKerbal.CrewName), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00074 = <<1>> died due to lack of Electrical Charge to run cryogenics + Utilities.Log("DeepFreezer - kerbal " + deathKerbal.CrewName + " died due to lack of Electrical charge to run cryogenics"); + kerbalsToDelete.Add(deathKerbal); + if (!flatline.isPlaying && DeepFreeze.Instance.DFsettings.BeepSoundsActive) + { + flatline.Play(); + } + } + kerbalsToDelete.ForEach(id => _StoredCrewList.Remove(id)); + } + else //NON-Fatal option set. Thaw them all. + { + Utilities.Log_Debug("DeepFreezer deathRoll reached, Kerbals all don't die... They just Thaw out..."); + deathCounter = currenttime; + //all kerbals thaw out + emergencyThawInProgress = true; //This will trigger FixedUpdate to thaw all frozen kerbals in the part, one by one. + } + } + } + } + else // no frozen kerbals, so just update last time EC checked + { + if (CheatOptions.InfiniteElectricity) + { + Utilities.Log_Debug("Infinite EC cheat on"); + } + else + { + Utilities.Log_Debug("No frozen kerbals for EC consumption in part " + part.name); + } + timeSinceLastECtaken = (float)currenttime; + deathCounter = currenttime; + FrznChargeUsage = 0f; + } + } + //Utilities.Log_Debug("ChkOngoingEC end"); + } + + private void ChkOngoingTemp(PartInfo partInfo) + { + // The follow section of code checks Temperatures when we have RegTempReqd set to true in the master config file. + // This check is done when we have frozen kerbals on board. + // But due to bugs in KSP with EC and SolarPanels at high timewarp if timewarp is > 4x we turn it off. + // If the temperature is too high and fatal option is on, we roll the dice. There is a 1 in 3 chance a Kerbal will DIE!!!! + // If fatal option is off all frozen kerbals are thawed + double currenttime = Planetarium.GetUniversalTime(); + double timeperiod = currenttime - timeSinceLastTmpChk; + //Utilities.Log_Debug("ChkOngoingTemp start time=" + Time.time.ToString() + ",timeSinceLastTmpChk=" + timeSinceLastTmpChk.ToString() + ",Planetarium.UniversalTime=" + Planetarium.GetUniversalTime().ToString() + " timeperiod=" + timeperiod.ToString()); + if (timeperiod > updateECTempInterval) //only update every udpateECTempInterval to avoid request resource bug when amounts are too small + { + if (TotalFrozen > 0) //We have frozen Kerbals, generate and check heat + { + //Add Heat for equipment monitoring frozen kerbals + double heatamt = heatamtMonitoringFrznKerbals / 60.0f * timeperiod * TotalFrozen; + if (heatamt > 0) part.AddThermalFlux(heatamt); + Utilities.Log_Debug("Added " + heatamt + " kW of heat for monitoring " + TotalFrozen + " frozen kerbals"); + if (part.temperature < DeepFreeze.Instance.DFsettings.RegTempMonitor) + { + Utilities.Log_Debug("DeepFreezer Temperature check is good parttemp=" + part.temperature + ",MaxTemp=" + DeepFreeze.Instance.DFsettings.RegTempMonitor); + if (TempChkMsg != null) ScreenMessages.RemoveMessage(TempChkMsg); + _FrzrTmp = FrzrTmpStatus.OK; + tmpdeathCounter = currenttime; + // do warning if within 40 and 20 kelvin + double tempdiff = DeepFreeze.Instance.DFsettings.RegTempMonitor - part.temperature; + if (tempdiff <= 40) + { + _FrzrTmp = FrzrTmpStatus.WARN; + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00075"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00075 = Check Temperatures, Freezer getting hot + } + else + { + if (tempdiff < 20) + { + _FrzrTmp = FrzrTmpStatus.RED; + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00076"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00076 = Warning!! Check Temperatures NOW, Freezer getting very hot + } + } + timeSinceLastTmpChk = (float)currenttime; + partInfo.TempWarning = false; + } + else + { + // OVER TEMP I'm Melting!!!! + Debug.Log("DeepFreezer Part Temp TOO HOT, Kerbals are going to melt parttemp=" + part.temperature); + if (!partInfo.TempWarning) + { + if (TimeWarp.CurrentRateIndex > 1) Utilities.stopWarp(); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00077"), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00077 = Temperature getting too hot for kerbals to remain frozen. + partInfo.TempWarning = true; + } + _FrzrTmp = FrzrTmpStatus.RED; + Utilities.Log_Debug("DeepFreezer tmpdeathCounter = {0}" , tmpdeathCounter.ToString()); + if (TempChkMsg != null) ScreenMessages.RemoveMessage(TempChkMsg); + TempChkMsg = ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00078", (tmpdeathRoll - (currenttime - tmpdeathCounter)).ToString("######0"))); //#autoLOC_DF_00078 = Freezer Over Temp : Systems critical in <<1>> secs + if (currenttime - tmpdeathCounter > tmpdeathRoll) + { + Utilities.Log_Debug("DeepFreezer tmpdeathRoll reached, roll the dice..."); + tmpdeathCounter = currenttime; + partInfo.TempWarning = false; + //a kerbal dies + if (DeepFreeze.Instance.DFsettings.fatalOption) + { + int dice = rnd.Next(1, _StoredCrewList.Count); // Randomly select a Kerbal to kill. + Utilities.Log_Debug("DeepFreezer A Kerbal dies dice=" + dice); + FrznCrewMbr deathKerbal = _StoredCrewList[dice - 1]; + DeepFreeze.Instance.KillFrozenCrew(deathKerbal.CrewName); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00079", deathKerbal.CrewName), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00079 = <<1>> died due to overheating, cannot keep frozen + Debug.Log("DeepFreezer - kerbal " + deathKerbal.CrewName + " died due to overheating, cannot keep frozen"); + _StoredCrewList.Remove(deathKerbal); + + if (!flatline.isPlaying && DeepFreeze.Instance.DFsettings.BeepSoundsActive) + { + flatline.Play(); + } + } + else //NON-fatal option set. Thaw them all. + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00080"), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00080 = Over Temperature - Emergency Thaw in Progress. + Utilities.Log_Debug("DeepFreezer deathRoll reached, Kerbals all don't die... They just Thaw out..."); + //all kerbals thaw out + emergencyThawInProgress = true; //This will trigger FixedUpdate to thaw all frozen kerbals in the part, one by one. + } + } + } + } + else // no frozen kerbals, so just update last time tmp checked + { + timeSinceLastTmpChk = (float)currenttime; + } + } + //Utilities.Log_Debug("ChkOngoingTemp end"); + } + + private void SetCryopodVariables() + { + if (cryopodVariables == null) + { + cryopodVariables = new List(); + } + else + { + cryopodVariables.Clear(); + } + //Only do this in Flight Scene or ONLY Pods that use AdvTransparentPod module in Editor Scene. Otherwise Internal appears in editor scene orientated incorrectly. + if (HighLogic.LoadedSceneIsFlight || (HighLogic.LoadedSceneIsEditor && DFInstalledMods.IsJSITransparentPodsInstalled && JSITransparentPodModule != null)) + { + if (part.internalModel == null) + { + part.CreateInternalModel(); + if (part.internalModel != null && HighLogic.LoadedSceneIsFlight) + { + part.internalModel.Initialize(part); + part.internalModel.SpawnCrew(); + StartCoroutine(UnregisterPortraits()); + } + } + for (int i = 0; i < FreezerSize; i++) + { + CryopodVariables entry = new CryopodVariables(); + + if (isPartAnimated) + entry.windowName = "Animated-Cryopod-" + (i + 1) + "-Window"; + else + { + entry.windowName = "Cryopod-" + (i + 1) + "-Window"; + } + entry.podName = "Animated-Cryopod-" + (i + 1); + entry.podAnimation = part.internalModel.FindModelComponent(entry.podName); + entry.camName = "FrzCam" + (i + 1); + entry.camera = part.internalModel.FindModelComponent(entry.camName); + entry.windowAnimation = part.internalModel.FindModelComponent(entry.windowName); + entry.extwindowRenderer = part.FindModelComponent(entry.windowName); + entry.intwindowRenderer = part.internalModel.FindModelComponent(entry.windowName); + entry.extwindowAnimation = part.FindModelComponent(entry.windowName); + entry.stripName = "lightStrip-Animated-Cryopod-" + (i + 1); + entry.stripAnimation = part.internalModel.FindModelComponent(entry.stripName); + cryopodVariables.Add(entry); + } + if (isPodExternal && hasJSITransparentPod && part.internalModel != null) + { + External_Window_Occluder = Utilities.FindInChildren(part.internalModel.transform, "External_Window_Occluder"); + if (External_Window_Occluder != null && TransparentSpecularShader != null && depthMaskShader != null) + { + Renderer[] renderers = External_Window_Occluder.GetComponentsInChildren(); + //Assume the first one found. + External_Window_Occluder_Renderer = renderers[0]; + External_Window_Material_Depth = External_Window_Occluder_Renderer.material; + if (cryopodVariables[0].extwindowRenderer != null) + { + External_Window_Material_Ice = new Material(cryopodVariables[0].extwindowRenderer.material); + if (TransparentSpecularShader != null) + { + External_Window_Material_Ice.shader = TransparentSpecularShader; + } + } + External_Window_Occluder_Anim = External_Window_Occluder_Renderer.transform.gameObject.GetComponent(); + } + } + } + } + + private IEnumerator UnregisterPortraits(bool activeCheck = true) + { + yield return null; + //If not the active vessel. Unregister the portraits. + if (FlightGlobals.ActiveVessel != null && (!activeCheck || (part.vessel.persistentId != FlightGlobals.ActiveVessel.persistentId))) + { + if (KerbalPortraitGallery.Instance != null) + { + for (int i = 0; i < part.internalModel.seats.Count; i++) + { + if (part.internalModel.seats[i].crew != null && part.internalModel.seats[i].crew.KerbalRef != null) + { + KerbalPortraitGallery.Instance.UnregisterActiveCrew(part.internalModel.seats[i].crew.KerbalRef); + } + } + } + } + } + + private IEnumerator AddPortraits() + { + yield return null; + if (KerbalPortraitGallery.Instance != null) + { + var activeCrew = KerbalPortraitGallery.Instance.ActiveCrewItems; + for (int i = 0; i < part.internalModel.seats.Count; i++) + { + if (part.internalModel.seats[i].crew != null && part.internalModel.seats[i].crew.KerbalRef != null) + { + bool found = false; + for (int j = 0; j < activeCrew.Count; j++) + { + if (activeCrew[j].kerbal.name == part.internalModel.seats[i].crew.name) + { + found = true; + break; + } + } + if (!found) + { + KerbalPortraitGallery.Instance.RegisterActiveCrew(part.internalModel.seats[i].crew.KerbalRef); + } + } + } + } + } + + public override void OnLoad(ConfigNode node) + { + //Debug.Log("DeepFreezer onLoad"); + base.OnLoad(node); + cryopodstateclosed = new bool[FreezerSize]; + seatTakenbyFrznKerbal = new bool[FreezerSize]; + loadcryopodstatepersistent(); + loadexternaldoorstatepersistent(); + //Debug.Log("OnLoad: " + node); + //Debug.Log("DeepFreezer end onLoad"); + } + + public override void OnStart(StartState state) + { + Debug.Log("DeepFreezer OnStart"); + base.OnStart(state); + //Set the GameEvents we are interested in + if (HighLogic.LoadedSceneIsFlight) + { + GameEvents.onCrewTransferPartListCreated.Add(onCrewTransferPartListCreated); + GameEvents.onCrewTransferred.Add(onCrewTransferred); + GameEvents.onVesselChange.Add(OnVesselChange); + GameEvents.onCrewBoardVessel.Add(OnCrewBoardVessel); + GameEvents.onCrewOnEva.Add(onCrewOnEva); + GameEvents.onVesselDestroy.Add(onVesselDestroy); + GameEvents.OnCameraChange.Add(OnCameraChange); + GameEvents.onVesselGoOffRails.Add(onVesselGoOffRails); + GameEvents.onVesselCrewWasModified.Add(OnVesselCrewModified); + DFGameEvents.onKerbalFrozen.Add(OnKerbalFreezeThaw); + DFGameEvents.onKerbalThaw.Add(OnKerbalFreezeThaw); + GameEvents.onVesselSwitching.Add(OnVesselSwitching); + onATPPodSettingChanged = GameEvents.FindEvent>("onATPPodSettingChanged"); + if (onATPPodSettingChanged != null) + { + onATPPodSettingChanged.Add(OnATPPodSettingChanged); + } + } + if (part.Modules.Contains("JSIAdvTransparentPod")) + { + hasJSITransparentPod = true; + } + //Set Shaders for changing the Crypod Windows + try + { + TransparentSpecularShader = Shader.Find(TransparentSpecularShaderName); + } + catch (Exception ex) + { + Utilities.Log_Debug("Get transparentShader " + TransparentSpecularShaderName + " failed. Error:" + ex); + } + try + { + depthMaskShader = Shader.Find(DepthMaskShaderName); + } + catch (Exception ex) + { + Utilities.Log_Debug("Get DepthMaskShader " + DepthMaskShaderName + " failed. Error:" + ex); + } + if (TransparentSpecularShader == null) + { + Utilities.Log_Debug("DepthMaskShader " + DepthMaskShaderName + " not found."); + } + try + { + KSPSpecularShader = Shader.Find(KSPSpecularShaderName); + } + catch (Exception ex) + { + Utilities.Log_Debug("Get " + KSPSpecularShaderName + " failed. Error:" + ex); + } + if (KSPSpecularShader == null) + { + Utilities.Log_Debug("KSPSpecularShader " + KSPSpecularShaderName + " not found."); + } + + if (JSITransparentPodModule == null && part.Modules.Contains("JSIAdvTransparentPod")) + { + JSITransparentPodModule = part.Modules["JSIAdvTransparentPod"]; + } + SetCryopodVariables(); + + // Setup the sounds + ext_door = gameObject.AddComponent(); + ext_door.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/externaldoorswitch"); + ext_door.volume = .7F; + ext_door.panStereo = 0; + ext_door.spatialBlend = 0; + ext_door.rolloffMode = AudioRolloffMode.Linear; + ext_door.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.panStereo = 0; + mon_beep.spatialBlend = 0; + mon_beep.rolloffMode = AudioRolloffMode.Logarithmic; + mon_beep.maxDistance = 10f; + mon_beep.minDistance = 8f; + mon_beep.dopplerLevel = 0f; + //mon_beep.panLevel = 0f; + mon_beep.playOnAwake = false; + mon_beep.priority = 255; + mon_beep.Stop(); + flatline = gameObject.AddComponent(); + flatline.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/flatline"); + flatline.volume = 1; + flatline.panStereo = 0; + mon_beep.spatialBlend = 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.panStereo = 0; + mon_beep.spatialBlend = 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.panStereo = 0; + mon_beep.spatialBlend = 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.panStereo = 0; + mon_beep.spatialBlend = 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.panStereo = 0; + mon_beep.spatialBlend = 0; + ding_ding.rolloffMode = AudioRolloffMode.Linear; + ding_ding.Stop(); + charge_up = gameObject.AddComponent(); + charge_up.clip = GameDatabase.Instance.GetAudioClip("REPOSoftTech/DeepFreeze/Sounds/charge_up"); + charge_up.volume = 1; + charge_up.panStereo = 0; + mon_beep.spatialBlend = 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 && PartHasDoor) + { + externalDoorAnim = null; + var Dooranims = part.FindModelAnimators(animationName); + if (Dooranims.Length > 0) + { + externalDoorAnim = Dooranims[0]; + } + if (externalDoorAnim == null) + { + Utilities.Log_Debug("Part has external animation defined but cannot find the animation on the part"); + ExternalDoorActive = false; + Events["eventOpenDoors"].active = false; + Events["eventCloseDoors"].active = false; + if (transparentTransforms != string.Empty) + part.setTransparentTransforms(transparentTransforms); + } + else + { + SetIVAOccluders(); + Utilities.Log_Debug("Part has external animation, check if JSITransparentPods is installed and process"); + if (DFInstalledMods.IsJSITransparentPodsInstalled) + { + Utilities.Log_Debug("JSITransparentPods installed, set doorstate"); + ExternalDoorActive = true; + if (_externaldoorstate == DoorState.OPEN) + { + StartCoroutine(openDoors(float.MaxValue)); + } + else + { + StartCoroutine(closeDoors(float.MinValue)); + } + } + else //RPM is not installed, disable the doors. + { + Utilities.Log_Debug("JSITransparentPods NOT installed, set transparent transforms"); + ExternalDoorActive = false; + Events["eventOpenDoors"].active = false; + Events["eventCloseDoors"].active = false; + Utilities.Log_Debug("door actions/events off"); + if (transparentTransforms != string.Empty) + part.setTransparentTransforms(transparentTransforms); + } + } + } + + if (DFInstalledMods.IsRTInstalled) + { + Fields["isRTConnected"].guiActive = true; + } + else + { + Fields["isRTConnected"].guiActive = false; + } + + timeLoadedOffrails = Planetarium.GetUniversalTime(); + IsRTInstalled = DFInstalledMods.IsRTInstalled; + Debug.Log("DeepFreezer END OnStart"); + } + + public override void OnSave(ConfigNode node) + { + //Debug.Log("DeepFreezer onSave"); + savecryopodstatepersistent(); + saveexternaldoorstatepersistent(); + base.OnSave(node); + //Debug.Log("OnSave: " + node); + //Debug.Log("DeepFreezer end onSave"); + } + + private void OnDestroy() + { + //Remove GameEvent callbacks. + Debug.Log("DeepFreezer OnDestroy"); + + GameEvents.onCrewTransferPartListCreated.Remove(onCrewTransferPartListCreated); + GameEvents.onCrewTransferred.Remove(onCrewTransferred); + GameEvents.onVesselChange.Remove(OnVesselChange); + GameEvents.onCrewBoardVessel.Remove(OnCrewBoardVessel); + GameEvents.onCrewOnEva.Remove(onCrewOnEva); + GameEvents.onVesselDestroy.Remove(onVesselDestroy); + GameEvents.OnCameraChange.Remove(OnCameraChange); + GameEvents.onVesselGoOffRails.Remove(onVesselGoOffRails); + GameEvents.onVesselCrewWasModified.Remove(OnVesselCrewModified); + DFGameEvents.onKerbalFrozen.Remove(OnKerbalFreezeThaw); + DFGameEvents.onKerbalThaw.Remove(OnKerbalFreezeThaw); + GameEvents.onVesselSwitching.Remove(OnVesselSwitching); + if (onATPPodSettingChanged != null) + { + onATPPodSettingChanged.Remove(OnATPPodSettingChanged); + } + + Debug.Log("DeepFreezer END OnDestroy"); + } + + private void OnVesselSwitching(Vessel oldVsl, Vessel newVsl) + { + if (part.vessel == null) + { + return; + } + + if (oldVsl.persistentId == part.vessel.persistentId) + { + StartCoroutine(UnregisterPortraits(false)); + return; + } + + if (newVsl.persistentId == part.vessel.persistentId) + { + if (HighLogic.LoadedSceneIsFlight || (HighLogic.LoadedSceneIsEditor && DFInstalledMods.IsJSITransparentPodsInstalled && JSITransparentPodModule != null)) + { + if (part.internalModel == null) + { + part.CreateInternalModel(); + if (part.internalModel != null && HighLogic.LoadedSceneIsFlight) + { + part.internalModel.Initialize(part); + } + } + InternalSeat seat; + for (int i = 0, iC = part.internalModel.seats.Count; i < iC; ++i) + { + seat = part.internalModel.seats[i]; + if (seat.kerbalRef == null) + { + seat.SpawnCrew(); + } + } + StartCoroutine(AddPortraits()); + } + } + } + + private void OnATPPodSettingChanged(Part inPart, string setting) + { + if (inPart.persistentId == part.persistentId && (PartHasDoor || isPodExternal)) + { + if (IsFreezeActive || IsThawActive) //Don't do if a freeze/thaw is running. It will be done when they finish automatically. + { + return; + } + try + { + checkRPMPodTransparencySetting(); + RPMPodOccluderProcessing(); + } + catch (Exception ex) + { + Utilities.Log("Exception attempting to check RPM transparency settings. Report this error on the Forum Thread."); + Utilities.Log("Err: " + ex); + } + } + } + + #region Events + + private void OnKerbalFreezeThaw(Part eventPart, ProtoCrewMember crew) + { + if (eventPart.persistentId == part.persistentId) + { + cryopodEvents.SyncEvents(); + } + } + + private void OnVesselCrewModified(Vessel vessel) + { + if (part.vessel != null && part.vessel.id == vessel.id) + { + cryopodEvents.SyncEvents(); + } + } + + private void removeFreezeEvent(string CrewMember) + { + try + { + //BaseEvent item = Events.Find(v => v.name == "Freeze " + CrewMember); // Find the Freeze event for the CrewMember + //if (item != null) + //{ + // Events.Remove(item); // Remove it + + if (cryopodEvents.RemoveFreezeEvent(CrewMember)) + { + lastRemove = Time.time; // we check this time when we do updateevents because if it is done too quickly the GUI goes crazy + UIPartActionWindow window = UIPartActionController.Instance.GetItem(part); + if (window != null) + { + window.displayDirty = true; + } + } + } + catch (Exception ex) + { + Debug.Log("Exception removing Freeze Event for " + CrewMember); + Debug.Log("Err: " + ex); + } + } + + private void removeThawEvent(string frozenkerbal) + { + try + { + if (cryopodEvents.RemoveThawEvent(frozenkerbal)) + { + lastRemove = Time.time; // we check this time when we do updateevents because if it is done too quickly the GUI goes crazy + UIPartActionWindow window = UIPartActionController.Instance.ItemListGet(part); + if (window != null) + { + window.displayDirty = true; + } + } + } + catch (Exception ex) + { + Debug.Log("Exception removing Thaw Event for " + frozenkerbal); + Debug.Log("Err: " + ex); + } + } + + #endregion Events + + #region FrzKerbals + + //This region contains the methods for freezing a kerbal + + private void ProcessFreezeKerbal() + { + Utilities.Log_Debug("DeepFreezer FreezeActive ToFrzeKerbal = " + ToFrzeKerbal + " Seat =" + ToFrzeKerbalSeat); + switch (FreezeStepInProgress) + { + case 0: + //Begin + Utilities.Log_Debug("Freeze Step 0"); + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + { + charge_up.Play(); // Play the sound effects. + charge_up.loop = true; + } + // If we are in IVA mode we switch to the internal camera in front of their cryopod. + if (vesselisinIVA || vesselisinInternal) + { + setIVAFrzrCam(ToFrzeKerbalSeat); + } + + if (partHasStripLights && DeepFreeze.Instance.DFsettings.StripLightsActive) + { + startStripLightFlash(ToFrzeKerbalSeat); + } + FreezeStepInProgress = 1; + break; + + case 1: + //get Electric Charge and Glykerol + #region Get EC for Freeze + Utilities.Log_Debug("Freeze Step 1"); + double ECTotal = 0f; + if (!CheatOptions.InfiniteElectricity && !Utilities.requireResource(vessel, EC, ChargeRate, false, true, false, out ResAvail, out ECTotal)) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00081"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00081 = Insufficient electric charge to freeze kerbal + FreezeKerbalAbort(ActiveFrzKerbal); + } + else + { + if (CheatOptions.InfiniteElectricity) + { + ECTotal = ChargeRate; + } + else + { + Utilities.requireResource(vessel, EC, ChargeRate, true, true, false, out ResAvail, out ECTotal); + } + StoredCharge = StoredCharge + ChargeRate; + if (FreezeMsg != null) ScreenMessages.RemoveMessage(FreezeMsg); + FreezeMsg = ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00082", StoredCharge.ToString("######0"))); //#autoLOC_DF_00082 = \u0020Cryopod - Charging: <<1>> + if (DeepFreeze.Instance.DFsettings.RegTempReqd) + { + part.AddThermalFlux(heatamtThawFreezeKerbal); + } + Utilities.Log_Debug("DeepFreezer Drawing Charge StoredCharge =" + StoredCharge.ToString("0000.00") + " ChargeRequired =" + ChargeRequired); + if (StoredCharge >= ChargeRequired) + { + if (FreezeMsg != null) ScreenMessages.RemoveMessage(FreezeMsg); + if (Utilities.requireResource(vessel, Glykerol, GlykerolRequired, true, true, false, out ResAvail, out ECTotal)) + { + charge_up.Stop(); // stop the sound effects + FreezeStepInProgress = 2; + } + else //Not enough Glykerol - abort + { + Utilities.Log_Debug("Not enough Glykerol - Aborting"); + FreezeKerbalAbort(ActiveFrzKerbal); + } + } + } + break; +#endregion + case 2: + //close the Pod door Hal + #region Close the Pod Door + Utilities.Log_Debug("Freeze Step 2"); + + if (partHasInternals && isPodExternal) + // Part has no animated cryopods but has internals. skip to step 3. + { + //cryopodstateclosed[ToFrzeKerbalSeat] = true; + //savecryopodstatepersistent(); + FreezeStepInProgress = 3; + } + else + { + if (partHasInternals && isPartAnimated) + { + if (!ClosePodAnimPlaying) // If animation not already playing start it playing. + { + Utilities.Log_Debug("Closing the cryopod"); + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + { + hatch_lock.Play(); // Play the sound effects. + machine_hum.Play(); + machine_hum.loop = true; + } + ClosePodAnimPlaying = true; + closeCryopod(ToFrzeKerbalSeat, 1f); + //cryopodstateclosed[ToFrzeKerbalSeat] = true; + //savecryopodstatepersistent(); + } + else // Animation is already playing, check if it has finished. + { + if (cryopodVariables[ToFrzeKerbalSeat].podAnimation != null) + { + if (cryopodVariables[ToFrzeKerbalSeat].podAnimation.IsPlaying("Close")) + { + Utilities.Log_Debug("waiting for the pod animation to complete the freeze"); + ClosePodAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 3."); + ClosePodAnimPlaying = false; + FreezeStepInProgress = 3; + } + } + else + { + //There is no animation found? Skip to step 3. + Utilities.Log_Debug("Animation disappeared. go to step 3."); + ClosePodAnimPlaying = false; + FreezeStepInProgress = 3; + } + } + } + else + { + //Part is not animated, skip to step 4. + ClosePodAnimPlaying = false; + cryopodstateclosed[ToFrzeKerbalSeat] = true; + savecryopodstatepersistent(); + FreezeStepInProgress = 4; + } + } + break; + #endregion + + case 3: + //Freeze the window + Utilities.Log_Debug("Freeze Step 3"); + if (partHasInternals) + { + if (!FreezeWindowAnimPlaying) // If animation not already playing start it playing. + { + Utilities.Log_Debug("freezing the cryopod window"); + machine_hum.Stop(); // stop the sound effects + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + ice_freeze.Play(); + FreezeWindowAnimPlaying = true; + freezeCryopodWindow(ToFrzeKerbalSeat, 1f); + } + else // Animation is already playing, check if it has finished. + { + bool lostAnimation = true; + if (isPodExternal) + { + if (External_Window_Occluder_Anim != null) + { + lostAnimation = false; + if (External_Window_Occluder_Anim.IsPlaying("CryopodWindowClose")) + { + Utilities.Log_Debug("waiting for the window animation to complete the freeze"); + FreezeWindowAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 4."); + FreezeWindowAnimPlaying = false; + FreezeStepInProgress = 4; + cryopodstateclosed[ToFrzeKerbalSeat] = true; + savecryopodstatepersistent(); + } + } + else if (cryopodVariables[ToFrzeKerbalSeat].extwindowAnimation != null) + { + lostAnimation = false; + if (cryopodVariables[ToFrzeKerbalSeat].extwindowAnimation.IsPlaying("CryopodWindowClose")) + { + Utilities.Log_Debug("waiting for the window animation to complete the freeze"); + FreezeWindowAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 4."); + FreezeWindowAnimPlaying = false; + FreezeStepInProgress = 4; + cryopodstateclosed[ToFrzeKerbalSeat] = true; + savecryopodstatepersistent(); + } + } + } + else + { + if (cryopodVariables[ToFrzeKerbalSeat].windowAnimation != null) + { + lostAnimation = false; + if (cryopodVariables[ToFrzeKerbalSeat].windowAnimation.IsPlaying("CryopodWindowClose")) + { + Utilities.Log_Debug("waiting for the window animation to complete the freeze"); + FreezeWindowAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 4."); + FreezeWindowAnimPlaying = false; + FreezeStepInProgress = 4; + cryopodstateclosed[ToFrzeKerbalSeat] = true; + savecryopodstatepersistent(); + } + } + } + if(lostAnimation) + { + Utilities.Log_Debug("Animation disappeared. go to step 4."); + //There is no animation found? Skip to step 4. + FreezeWindowAnimPlaying = false; + FreezeStepInProgress = 4; + cryopodstateclosed[ToFrzeKerbalSeat] = true; + savecryopodstatepersistent(); + } + } + } + else + { + //Part is not animated, skip to step 4. + FreezeWindowAnimPlaying = false; + FreezeStepInProgress = 4; + cryopodstateclosed[ToFrzeKerbalSeat] = true; + savecryopodstatepersistent(); + } + break; + + case 4: + //Finalise + Utilities.Log_Debug("Freeze Step 4"); + if (partHasInternals) + { + setCryopodWindowSpecular(ToFrzeKerbalSeat); + } + FreezeKerbalConfirm(ActiveFrzKerbal); + break; + } + } + + public void beginFreezeKerbal(ProtoCrewMember CrewMember) + { + //This method is the first called to Freeze a Kerbal it will check all the pre-conditions are right for freezing and then call FreezeKerbal if they are + try + { + if (DFIntMemory.FreezeThawActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00086"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00086 = Cannot run Freeze process on more than one Kerbal at a time + return; + } + if (FreezerSpace > 0 && part.protoModuleCrew.Contains(CrewMember)) // Freezer has space? and Part contains the CrewMember? + { + double GlykTotal = 0f; + if (!Utilities.requireResource(vessel, Glykerol, GlykerolRequired, false, true, false, out ResAvail, out GlykTotal)) // check we have Glykerol on board. 5 units per freeze event. This should be a part config item not hard coded. + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00083"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00083 = Insufficient Glykerol to freeze kerbal + } + else // We have enough Glykerol + { + if (DeepFreeze.Instance.DFsettings.RegTempReqd) // Temperature check is required + { + if ((float)part.temperature > DeepFreeze.Instance.DFsettings.RegTempFreeze) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00084", (DeepFreeze.Instance.DFsettings.TempinKelvin ? DeepFreeze.Instance.DFsettings.RegTempFreeze.ToString("######0") : (DeepFreeze.Instance.DFsettings.RegTempFreeze - 273.15d).ToString("######0")) + Fields["CabinTemp"].guiUnits), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00084 = Cannot Freeze while Temperature greater than <<1>> + return; + } + } + /* + if (DFInstalledMods.IsSMInstalled) // Check if Ship Manifest (SM) is installed? + { + if (IsSMXferRunning()) // SM is installed and is a Xfer running? If so we can't run a Freeze while a SMXfer is running. + { + ScreenMessages.PostScreenMessage("Cannot Freeze while Crew Xfer in progress", 5.0f, ScreenMessageStyle.UPPER_CENTER); + return; + } + }*/ + //if (_crewXferFROMActive || _crewXferTOActive) // We can't run a freeze process if a crewXfer is active, this is catching Stock Xfers. + if (IsCrewXferRunning) // We can't run a freeze process if a crewXfer is active, this is catching Stock Xfers. + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00085"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00085 = Cannot Freeze while Crew Xfer in progress + return; + } + if (IsThawActive || IsFreezeActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00086"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00086 = Cannot run Freeze process on more than one Kerbal at a time + return; + } + if (DFInstalledMods.IsRTInstalled) + { + if (part.vessel.GetCrewCount() == 1 && RTlastKerbalFreezeWarn == false) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00087"), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00087 = RemoteTech Detected. Press Freeze Again if you want to Freeze your Last Active Kerbal + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00088"), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00088 = An Active connection or Active Kerbal is Required On-Board to Initiate Thaw Process + RTlastKerbalFreezeWarn = true; + return; + } + RTlastKerbalFreezeWarn = false; + } + FreezeKerbal(CrewMember); // Begin the Freezing Process + } + } + else + { + if (FreezerSpace == 0) + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00089"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00089 = Cannot freeze kerbal. Freezer is full + } + } + catch (Exception ex) + { + Debug.Log("Exception attempting to start Freeze for " + CrewMember); + Debug.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00090"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00090 = Cannot freeze kerbal at this time + } + } + + private void FreezeKerbal(ProtoCrewMember CrewMember) + { + //this method sets all the vars for the kerbal about to be frozen and starts the freezing process (sound). + //if we are in IVA camera mode it will switch to the view in front of the kerbal and run the cryopod closing animation. + Utilities.Log_Debug("Freeze kerbal called"); + CrewHatchController.fetch.DisableInterface(); + ActiveFrzKerbal = CrewMember; // set the Active Freeze Kerbal + ToFrzeKerbal = CrewMember.name; // set the Active Freeze Kerbal name + Utilities.Log_Debug("FreezeKerbal " + CrewMember.name); + Utilities.dmpKerbalRefs(null, partHasInternals ? part.internalModel.seats[CrewMember.seatIdx].kerbalRef : null, CrewMember.KerbalRef); + if (partHasInternals) + Utilities.Log_Debug("Seatindx=" + CrewMember.seatIdx + ",Seatname=" + CrewMember.seat.seatTransformName); + try + { + ToFrzeKerbalSeat = CrewMember.seatIdx; + } + catch (Exception) + { + Debug.Log("Unable to find internal seat index for " + CrewMember.name); + //Debug.Log("Err: " + ex); + ToFrzeKerbalSeat = -1; // Set their seat + } + try + { + ToFrzeKerbalXformNme = CrewMember.seat.seatTransformName; + } + catch (Exception ex) + { + Debug.Log("Unable to find internal seat for " + CrewMember.name); + Debug.Log("Err: " + ex); + ToFrzeKerbalXformNme = "Unknown"; // Set their set Xform Name + } + Utilities.Log_Debug("FreezeKerbal ACtiveFrzKerbal=" + ActiveFrzKerbal.name + ",ToFrzeKerbalSeat=" + ToFrzeKerbalSeat + ",ToFrzeKerbalXformNme=" + ToFrzeKerbalXformNme); + FreezeStepInProgress = 0; + IsFreezeActive = true; // Set the Freezer actively freezing mode on + if (DFGameEvents.onKerbalFreezing != null) + DFGameEvents.onKerbalFreezing.Fire(this.part, CrewMember.name); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00091"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00091 = Starting Freeze process + Utilities.Log_Debug("ActiveFrzKerbal=" + ActiveFrzKerbal.name + ",ToFrzeKerbal=" + ToFrzeKerbal + ",SeatIdx=" + ToFrzeKerbalSeat + ",seat transform name=" + ToFrzeKerbalXformNme); + Utilities.Log_Debug("FreezeKerbal ended"); + } + + private void FreezeKerbalAbort(ProtoCrewMember CrewMember) + { + try + { + Utilities.Log_Debug("FreezeKerbalAbort " + CrewMember.name + " seat " + ToFrzeKerbalSeat); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00092"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //autoLOC_DF_00092 = Freezing Aborted + Utilities.setFrznKerbalLayer(part, CrewMember, true); + if (partHasInternals) + { + if (vesselisinIVA || vesselisinInternal) + { + setIVAFrzrCam(ToFrzeKerbalSeat); + } + if (isPartAnimated) + openCryopod(ToFrzeKerbalSeat, float.MaxValue); + if (isPartAnimated || (isPodExternal && DFInstalledMods.IsJSITransparentPodsInstalled && _prevRPMTransparentpodSetting == "ON")) + thawCryopodWindow(ToFrzeKerbalSeat, float.MaxValue); + cryopodstateclosed[ToFrzeKerbalSeat] = false; + savecryopodstatepersistent(); + if (partHasStripLights && DeepFreeze.Instance.DFsettings.StripLightsActive) + { + stopStripLightFlash(ToFrzeKerbalSeat); + } + } + + if (!AddKerbal(CrewMember, ToFrzeKerbalSeat)) + { + Debug.Log("FreezeKerbalAbort Procedure FAILED! Critical error"); + } + IsFreezeActive = false; // Turn the Freezer actively freezing mode off + OnATPPodSettingChanged(this.part, "A"); + FreezeStepInProgress = 0; + ClosePodAnimPlaying = false; + FreezeWindowAnimPlaying = false; + ToFrzeKerbal = ""; // Set the Active Freeze Kerbal to null + machine_hum.Stop(); // Stop the sound effects + charge_up.Stop(); + StoredCharge = 0; // Discharge all EC stored + UpdateCounts(); // Update the Crew counts + if (DFGameEvents.onKerbalFreezeAbort != null) + DFGameEvents.onKerbalFreezeAbort.Fire(this.part, CrewMember.name); + //Add them to the portrait cams. + //Portraits.RestorePortrait(part, CrewMember.KerbalRef); + base.StartCoroutine(CallbackUtil.DelayedCallback(1, new Callback(this.fireOnVesselChange))); + if (FreezeMsg != null) ScreenMessages.RemoveMessage(FreezeMsg); + CrewHatchController.fetch.EnableInterface(); + } + catch (Exception ex) + { + Utilities.Log("Unable to to cancel freeze of crewmember " + CrewMember.name); + Utilities.Log("Err: " + ex); + } + Utilities.Log_Debug("FreezeKerbalAbort ended"); + } + + private void FreezeKerbalConfirm(ProtoCrewMember CrewMember) + { + //this method runs with the freeze process is complete (EC consumed) + //it will store the frozen crew member's details in the _StorecrewList and KnownFrozenKerbals dictionary + //it will remove the kerbal from the part and set their status to dead and unknown + Utilities.Log_Debug("FreezeKerbalConfirm kerbal " + CrewMember.name + " seatIdx " + ToFrzeKerbalSeat); + StoredCharge = 0; // Discharge all EC stored + //Make them invisible + if (partHasInternals) + { + Utilities.setFrznKerbalLayer(part, CrewMember, false); + } + //Remove them + if (!RemoveKerbal(CrewMember, ToFrzeKerbalSeat)) + { + FreezeKerbalAbort(CrewMember); + } + else + { + //Set internal cam if in IVA mode + if (vesselisinIVA || vesselisinInternal) + { + setIVAFrzrCam(ToFrzeKerbalSeat); + } + if (partHasStripLights && DeepFreeze.Instance.DFsettings.StripLightsActive) + { + stopStripLightFlash(ToFrzeKerbalSeat); + } + UpdateCounts(); // Update the Crew counts + IsFreezeActive = false; // Turn the Freezer actively freezing mode off + OnATPPodSettingChanged(this.part, "A"); + ToFrzeKerbal = ""; // Set the Active Freeze Kerbal to null + ActiveFrzKerbal = null; // Set the Active Freeze Kerbal to null + removeFreezeEvent(CrewMember.name); // Remove the Freeze Event for this kerbal. + + if (DFInstalledMods.IskerbalismInstalled) // IF Kerbalism Installed, remove tracking. + { + Utilities.Log_Debug("kerbalism installed untrack kerbal=" + CrewMember.name); + try + { + KBDisableKerbal(CrewMember.name, true); + } + catch (Exception ex) + { + Utilities.Log("DeepFreeze Exception attempting to untrack a kerbal in Kerbalism. Report this error on the Forum Thread."); + Utilities.Log("DeepFreeze Err: " + ex); + } + } + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00093", CrewMember.name), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00093 = <<1>> frozen + + vessel.RebuildCrewList(); + if (DFGameEvents.onKerbalFrozen != null) + DFGameEvents.onKerbalFrozen.Fire(this.part, CrewMember); + CrewHatchController.fetch.EnableInterface(); + GameEvents.onVesselWasModified.Fire(vessel); + + if (DFInstalledMods.IsUSILSInstalled) // IF USI LS Installed, remove tracking. + { + Utilities.Log_Debug("USI/LS installed untrack kerbal=" + CrewMember.name); + try + { + USIUntrackKerbal(CrewMember.name); + if (this.part.vessel.GetVesselCrew().Count == 0) + { + Utilities.Log_Debug("USI/LS installed untrack vessel=" + this.part.vessel.id.ToString()); + USIUntrackVessel(this.part.vessel.id.ToString()); + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreeze Exception attempting to untrack a kerbal and/or vessel in USI/LS. Report this error on the Forum Thread."); + Utilities.Log("DeepFreeze Err: " + ex); + } + } + if ((vesselisinIVA || vesselisinInternal) && part.protoModuleCrew.Count == 0) + { + CameraManager.Instance.SetCameraFlight(); + } + } + Utilities.Log_Debug("FreezeCompleted"); + } + + private void USIUntrackKerbal(string crewmember) + //This will remove tracking of a frozen kerbal from USI Life Support MOD, so that they don't consume resources when they are thawed. + { + if (USIWrapper.APIReady && USIWrapper.InstanceExists) + { + USIWrapper.USIActualAPI.UntrackKerbal(crewmember); + bool checkTracked = USIWrapper.USIActualAPI.IsKerbalTracked(crewmember); + if (checkTracked) + { + Debug.Log("DeepFreeze has been unable to untrack kerbal " + crewmember + " in USI LS mod. Report this error on the Forum Thread."); + } + + } + else + { + Debug.Log("DeepFreeze has been unable to connect to USI LS mod. API is not ready. Report this error on the Forum Thread."); + } + } + + private void USIUntrackVessel(string vesselId) + //This will remove tracking of a frozen kerbal from USI Life Support MOD, so that they don't consume resources when they are thawed. + { + if (USIWrapper.APIReady && USIWrapper.InstanceExists) + { + USIWrapper.USIActualAPI.UntrackVessel(vesselId); + bool checkTracked = USIWrapper.USIActualAPI.IsVesselTracked(vesselId); + if (checkTracked) + { + Debug.Log("DeepFreeze has been unable to untrack vessel " + vesselId + " in USI LS mod. Report this error on the Forum Thread."); + } + + } + else + { + Debug.Log("DeepFreeze has been unable to connect to USI LS mod. API is not ready. Report this error on the Forum Thread."); + } + } + + private void KBDisableKerbal(string crewmember, bool disable) + //This will remove tracking of a frozen kerbal from USI Life Support MOD, so that they don't consume resources when they are thawed. + { + if (KBWrapper.APIReady) + { + KBWrapper.KBActualAPI.DisableKerbal(crewmember, disable); + } + else + { + Debug.Log("DeepFreeze has been unable to connect to Kerbalism mod. API is not ready. Report this error on the Forum Thread."); + } + } + + #endregion FrzKerbals + + #region ThwKerbals + + //This region contains the methods for thawing a kerbal + private void ProcessThawKerbal() + { + Utilities.Log_Debug("DeepFreezer ThawActive Kerbal = " + ToThawKerbal); + switch (ThawStepInProgress) + { + case 0: + //Begin + // Utilities.Log_Debug("Thaw Step 0"); + ThawKerbalStep0(ToThawKerbal); + if (vesselisinInternal) + { + setIVAFrzrCam(ToThawKerbalSeat); + } + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + { + charge_up.Play(); // Play the sound effects. + charge_up.loop = true; + } + ThawStepInProgress = 1; + break; + + case 1: + //Get EC and Glykerol + #region Get EC and Glykerol for Freeze + // Utilities.Log_Debug("Thaw Step 1"); + if (skipThawStep1) + { + Utilities.Log_Debug("Skipping step 1 of Thaw process"); + charge_up.Stop(); + ThawStepInProgress = 2; + break; + } + double totalAvail = 0f; + if (!CheatOptions.InfiniteElectricity && !Utilities.requireResource(vessel, EC, ChargeRate, false, true, false, out ResAvail, out totalAvail)) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00094"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00094 = Insufficient electric charge to thaw kerbal + ThawKerbalAbort(ToThawKerbal); + } + else + { + if (!CheatOptions.InfiniteElectricity) + { + Utilities.requireResource(vessel, EC, ChargeRate, true, true, false, out ResAvail, out totalAvail); + } + StoredCharge = StoredCharge + ChargeRate; + if (ThawMsg != null) ScreenMessages.RemoveMessage(ThawMsg); + ThawMsg = ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00095", StoredCharge.ToString("######0"))); //#autoLOC_DF_00095 = \u0020Cryopod - Charging:<<1>> + + if (DeepFreeze.Instance.DFsettings.RegTempReqd) + { + part.AddThermalFlux(heatamtThawFreezeKerbal); + } + if (StoredCharge >= ChargeRequired) + { + Utilities.Log_Debug("Stored charge requirement met. Have EC"); + if (ThawMsg != null) ScreenMessages.RemoveMessage(ThawMsg); + charge_up.Stop(); + ThawStepInProgress = 2; + } + } + break; + #endregion + + case 2: + //thaw the cryopod window + // Utilities.Log_Debug("Thaw Step 2"); + if (partHasInternals) + { + if (!ThawWindowAnimPlaying) // If animation not already playing start it playing. + { + Utilities.Log_Debug("Thawing the cryopod window"); + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + ice_freeze.Play(); + ThawWindowAnimPlaying = true; + if (isPartAnimated || (isPodExternal && DFInstalledMods.IsJSITransparentPodsInstalled && _prevRPMTransparentpodSetting == "ON")) + { + thawCryopodWindow(ToThawKerbalSeat, 1f); + } + if (partHasStripLights && DeepFreeze.Instance.DFsettings.StripLightsActive) + { + startStripLightFlash(ToThawKerbalSeat); + } + } + else // Animation is already playing, check if it has finished. + { + bool lostAnimation = true; + if (isPodExternal) + { + if (External_Window_Occluder_Anim != null) + { + lostAnimation = false; + if (External_Window_Occluder_Anim.IsPlaying("CryopodWindowOpen")) + { + Utilities.Log_Debug("waiting for the window animation to complete the freeze"); + ThawWindowAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 3."); + ThawWindowAnimPlaying = false; + ThawStepInProgress = 3; + } + } + else if (cryopodVariables[ToThawKerbalSeat].extwindowAnimation != null) + { + lostAnimation = false; + if (cryopodVariables[ToThawKerbalSeat].extwindowAnimation.IsPlaying("CryopodWindowOpen")) + { + Utilities.Log_Debug("waiting for the window animation to complete the thaw"); + ThawWindowAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 3."); + ThawWindowAnimPlaying = false; + ThawStepInProgress = 3; + } + } + } + else + { + if (cryopodVariables[ToThawKerbalSeat].windowAnimation != null) + { + lostAnimation = false; + if (cryopodVariables[ToThawKerbalSeat].windowAnimation.IsPlaying("CryopodWindowOpen")) + { + Utilities.Log_Debug("waiting for the pod animation to complete the thaw"); + ThawWindowAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 3."); + ThawWindowAnimPlaying = false; + ThawStepInProgress = 3; + } + } + } + if (lostAnimation) + { + { + Utilities.Log_Debug("Animation disappeared. go to step 3."); + //There is no animation found? Skip to step 3. + ThawWindowAnimPlaying = false; + ThawStepInProgress = 3; + } + } + } + } + else + { + //Part is not animated, skip to step 4. + ThawWindowAnimPlaying = false; + ThawStepInProgress = 4; + } + //} + break; + + case 3: + //open the Pod door Hal + #region Open the Pod Door + // Utilities.Log_Debug("Thaw Step 3"); + if (partHasInternals && isPartAnimated) + { + if (!OpenPodAnimPlaying) // If animation not already playing start it playing. + { + Utilities.Log_Debug("Opening the cryopod"); + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + { + hatch_lock.Play(); // Play the sound effects. + machine_hum.Play(); + machine_hum.loop = true; + } + OpenPodAnimPlaying = true; + openCryopod(ToThawKerbalSeat, 1f); + //cryopodstateclosed[ToThawKerbalSeat] = false; + //savecryopodstatepersistent(); + } + else // Animation is already playing, check if it has finished. + { + if (cryopodVariables[ToThawKerbalSeat].windowAnimation != null) + { + if (cryopodVariables[ToThawKerbalSeat].windowAnimation.IsPlaying("Open")) + { + // Utilities.Log_Debug("waiting for the pod animation to complete the thaw"); + OpenPodAnimPlaying = true; + } + else + { + Utilities.Log_Debug("Animation has completed. go to step 4."); + OpenPodAnimPlaying = false; + ThawStepInProgress = 4; + } + } + else + { + //There is no animation found? Skip to step 4. + Utilities.Log_Debug("Animation disappeared. go to step 4."); + OpenPodAnimPlaying = false; + ThawStepInProgress = 4; + } + } + } + else + { + //Part is not animated, skip to step 4. + OpenPodAnimPlaying = false; + cryopodstateclosed[ToThawKerbalSeat] = false; + savecryopodstatepersistent(); + ThawStepInProgress = 4; + } + break; + #endregion + + case 4: + //Finalise + // Utilities.Log_Debug("Thaw Step 4"); + ThawKerbalStep4(ToThawKerbal); + break; + } + } + + public void beginThawKerbal(string frozenkerbal) + { + try + { + Utilities.Log_Debug("beginThawKerbal " + frozenkerbal); + if (DFIntMemory.FreezeThawActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00098"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00098 = Cannot run Thaw process on more than one Kerbal at a time + return; + } + if (part.protoModuleCrew.Count >= part.CrewCapacity) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00096", frozenkerbal), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00096 = Cannot Thaw <<1>> Part is full + Utilities.Log_Debug("Cannot thaw " + frozenkerbal + " Part is full"); + } + else + { + /* + * if (DFInstalledMods.IsSMInstalled) // Check if Ship Manifest (SM) is installed? + { + if (IsSMXferRunning()) // SM is installed and is a Xfer running? If so we can't run a Freeze while a SMXfer is running. + { + ScreenMessages.PostScreenMessage("Cannot Thaw while Crew Xfer in progress", 5.0f, ScreenMessageStyle.UPPER_CENTER); + return; + } + } + */ + //if (_crewXferFROMActive || _crewXferTOActive) // We can't run a thaw process if a crewXfer is active, this is catching Stock Xfers. + if (IsCrewXferRunning) // We can't run a thaw process if a crewXfer is active, this is catching Stock Xfers. + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00097"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00097 = Cannot Thaw while Crew Xfer in progress + return; + } + if (IsThawActive || IsFreezeActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00098"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00098 = Cannot run Thaw process on more than one Kerbal at a time + return; + } + + ToThawKerbal = frozenkerbal; // Set the Active Thaw Kerbal to frozenkerbal name + IsThawActive = true; // Turn the Freezer actively thawing mode on + ThawStepInProgress = 0; + if (DFGameEvents.onKerbalThawing != null) + { + DFGameEvents.onKerbalThawing.Fire(this.part, frozenkerbal); + } + + CrewHatchController.fetch.DisableInterface(); + Utilities.Log_Debug("beginThawKerbal has started thawing process"); + } + } + catch (Exception ex) + { + Debug.Log("Exception attempting to start Thaw for " + frozenkerbal); + Debug.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00099"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00099 = Cannot thaw kerbal at this time + } + } + + private void ThawKerbalStep0(string frozenkerbal) + { + // First we find out Unowned Crewmember in the roster. + ProtoCrewMember kerbal = null; + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Unowned.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == frozenkerbal) + kerbal = enumerator.Current; + } + if (kerbal != null) + { + // Set our newly thawed Popsicle, er Kerbal, to Crew type again (from Unowned) and Assigned status (from Dead status). + Utilities.Log_Debug("set type to crew and assigned"); + kerbal.type = ProtoCrewMember.KerbalType.Crew; + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; + Utilities.Log_Debug("find the stored crew member"); + //Now we find our Crewmember in the stored crew list in the part. + FrznCrewMbr tmpcrew = null; // Find the thawed kerbal in the frozen kerbal list. + List.Enumerator enumerator2 = _StoredCrewList.GetEnumerator(); + while (enumerator2.MoveNext()) + { + if (enumerator2.Current.CrewName == frozenkerbal) + tmpcrew = enumerator2.Current; + } + if (tmpcrew != null) + { + //check if seat is empty, if it is we have to seat them in next available seat + Utilities.Log_Debug("frozenkerbal " + tmpcrew.CrewName + ",seatindx=" + tmpcrew.SeatIdx); + ToThawKerbalSeat = tmpcrew.SeatIdx; + if (partHasInternals) // All deepfreeze supplied parts have internals. + { + Utilities.Log_Debug("Part has internals"); + Utilities.Log_Debug("Checking their seat taken=" + part.internalModel.seats[tmpcrew.SeatIdx].taken); + ProtoCrewMember crew = part.internalModel.seats[tmpcrew.SeatIdx].crew; + if (crew != null) + { + // we check the internal seat has our Crewmember in it. Not some other kerbal. + if (crew.name == frozenkerbal) + { + int codestep = 0; + try + { + //seat is taken and it is by themselves. Expected condition. + //Check the KerbalRef isn't null. If it is we need to respawn them. (this shouldn't occur). + if (kerbal.KerbalRef == null) + { + Utilities.Log_Debug("Kerbal kerbalref is still null, respawn"); + kerbal.seat = part.internalModel.seats[tmpcrew.SeatIdx]; + kerbal.seatIdx = tmpcrew.SeatIdx; + ProtoCrewMember.Spawn(kerbal); + Utilities.Log_Debug("Kerbal kerbalref = " + kerbal.KerbalRef.GetInstanceID()); + } + codestep = 1; + if (kerbal.KerbalRef != null) + { + Utilities.subdueIVAKerbalAnimations(kerbal.KerbalRef); + } + Utilities.setFrznKerbalLayer(part, kerbal, true); //Set the Kerbal renderer layers on so they are visible again. + kerbal.KerbalRef.InPart = part; //Put their kerbalref back in the part. + kerbal.KerbalRef.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; + codestep = 2; + //Add them to the portrait cams. + DFPortraits.RestorePortrait(part, kerbal.KerbalRef); + base.StartCoroutine(CallbackUtil.DelayedCallback(1, new Callback(this.fireOnVesselChange))); + base.StartCoroutine(CallbackUtil.DelayedCallback(5, new Callback(this.checkPortraitRegistered), kerbal.KerbalRef)); + Utilities.Log_Debug("Expected condition met, kerbal already in their seat."); + codestep = 3; + try + { + if (DFInstalledMods.IsTexReplacerInstalled) + { + TexReplacerPersonaliseKerbal(kerbal.KerbalRef); + } + } + catch (Exception ex) + { + Debug.Log("Exception attempting to restore Kerbals Texture Replacer mod customisations. Report this error on the Forum Thread."); + Debug.Log("Err: " + ex); + } + codestep = 4; + // If in IVA mode set the camera to watch the process. + if (vesselisinIVA || vesselisinInternal) + setIVAFrzrCam(tmpcrew.SeatIdx); + codestep = 5; + if (ExternalDoorActive) + { + //now set the helmet state depending on the external door state. + if (_externaldoorstate == DoorState.CLOSED) + { + Utilities.setHelmetshaders(kerbal.KerbalRef, false); + } + else + { + Utilities.setHelmetshaders(kerbal.KerbalRef, true); + } + } + Utilities.Log_Debug("Finishing ThawKerbalStep0"); + } + catch (Exception ex) + { + Debug.Log("Exception attempting to add to seat for " + frozenkerbal); + Debug.Log("Part has Internals, and Frozen Kerbal was found codestep = " + codestep); + Debug.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00100"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + ThawKerbalAbort(frozenkerbal); + } + } + else //Seat is taken, but not by our frozen Kerbal, we can't continue. + { + Utilities.Log_Debug("Seat taken by someone else, Abort"); + Debug.Log("Could not start kerbal Thaw process as seat is taken by another kerbal. Very Very Bad. Report this to Mod thread"); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00100"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + ThawKerbalAbort(frozenkerbal); + } + } + else + // The Seat's Crew is set to NULL. This could happen when on UPGRADE from V0.17 and below, or where vessel is loaded in range of the active vessel on flight scene startup. + // and then the user switches to this vessel and thaws a kerbal. + { + Utilities.Log_Debug("Seat Crew KerbalRef is NULL re-add them at seatidx=" + tmpcrew.SeatIdx); + //this.part.internalModel.seats[tmpcrew.SeatIdx].taken = false; // Set their seat to NotTaken before we assign them back to their seat, not sure we really need this. + int codestep = 0; + try + { + part.internalModel.SitKerbalAt(kerbal, part.internalModel.seats[tmpcrew.SeatIdx]); + if (ExternalDoorActive) + { + //set the seat to allow helmet, this will cause the helmet to appear + kerbal.seat.allowCrewHelmet = true; + } + codestep = 1; + kerbal.seat.SpawnCrew(); + // Think this will get rid of the static that appears on the portrait camera + setseatstaticoverlay(part.internalModel.seats[tmpcrew.SeatIdx]); + if (kerbal.KerbalRef != null) + { + Utilities.subdueIVAKerbalAnimations(kerbal.KerbalRef); + } + Utilities.setFrznKerbalLayer(part, kerbal, true); //Set the Kerbal renderer layers on so they are visible again. + kerbal.KerbalRef.InPart = part; //Put their kerbalref back in the part. + kerbal.KerbalRef.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; + codestep = 2; + //Add them to the portrait cams. + DFPortraits.RestorePortrait(part, kerbal.KerbalRef); + base.StartCoroutine(CallbackUtil.DelayedCallback(1, new Callback(this.fireOnVesselChange))); + base.StartCoroutine(CallbackUtil.DelayedCallback(5, new Callback(this.checkPortraitRegistered), kerbal.KerbalRef)); + Utilities.Log_Debug("Just thawing crew and added to GUIManager"); + codestep = 3; + try + { + if (DFInstalledMods.IsTexReplacerInstalled) + { + TexReplacerPersonaliseKerbal(kerbal.KerbalRef); + } + } + catch (Exception ex) + { + Debug.Log("Exception attempting to restore Kerbals Texture Replacer mod customisations. Report this error on the Forum Thread."); + Debug.Log("Err: " + ex); + } + codestep = 4; + if (vesselisinIVA || vesselisinInternal) + setIVAFrzrCam(tmpcrew.SeatIdx); + codestep = 5; + if (ExternalDoorActive) + { + //now set the helmet state depending on the external door state. + if (_externaldoorstate == DoorState.CLOSED) + { + Utilities.setHelmetshaders(kerbal.KerbalRef, true); + } + else + { + Utilities.setHelmetshaders(kerbal.KerbalRef, true); + } + } + Utilities.Log_Debug("Finishing ThawKerbalStep0"); + } + catch (Exception ex) + { + Debug.Log("Exception attempting to add to seat for " + frozenkerbal); + Debug.Log("Seat Crew KerbalRef is NULL re-add them at seatidx=" + tmpcrew.SeatIdx + " codestep = " + codestep); + Debug.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00100"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + ThawKerbalAbort(frozenkerbal); + } + } + } + else //All DeepFreeze supplied parts have an internal. this is in case someone adds their own part with DeepFreezer Module attached. + { + Utilities.Log_Debug("Part has no internals, just add"); + try + { + part.AddCrewmember(kerbal); // Add them to the part anyway. + //seatTakenbyFrznKerbal[ToThawKerbalSeat] = false; + //kerbal.seat.SpawnCrew(); + } + catch (Exception ex) + { + Debug.Log("Exception attempting to add to seat for " + frozenkerbal); + Debug.Log("Where DeepFreezer Module is attached to internal-LESS part"); + Debug.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00100"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + ThawKerbalAbort(frozenkerbal); + } + } + } + else // This should NEVER occur. + { + Debug.Log("Could not find frozen kerbal in _StoredCrewList to Thaw, Very Very Bad. Report this to Mod thread"); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00100"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + ThawKerbalAbort(frozenkerbal); + } + } + else // This should NEVER occur. + { + Debug.Log("Could not find frozen kerbal in Unowned Crew List to Thaw, Very Very Bad. Report this to Mod thread"); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00100"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00100 = Code Error: Cannot thaw kerbal at this time, Check Log + ThawKerbalAbort(frozenkerbal); + } + } + + private void TexReplacerPersonaliseKerbal(Kerbal kerbal) + { + //This will re-personalise a kerbal who has been personalised using Texture replacer mod. + try + { + Utilities.Log_Debug("Texture Replacer installed. Re-PersonliseKerbal"); + if (TRWrapper.APIReady && TRWrapper.InstanceExists) + { + TRWrapper.TexRepPersonaliser.personaliseIva(kerbal); + } + else + { + Debug.Log("DeepFreeze has been unable to connect to Texture Replacer mod. API is not ready. Report this error on the Forum Thread."); + } + } + catch (Exception ex) + { + Debug.Log("Exception attempting to restore Kerbals Texture Replacer mod customisations. Report this error on the Forum Thread."); + Debug.Log("Err: " + ex); + } + } + + private void ThawKerbalAbort(String ThawKerbal) + { + Utilities.Log_Debug("ThawkerbalAbort called"); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00101"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00101 = Thawing Aborted + IsThawActive = false; // Turn the Freezer actively thawing mode off + OnATPPodSettingChanged(this.part, "A"); + ToThawKerbal = ""; // Set the Active Thaw Kerbal to null + StoredCharge = 0; // Discharge all EC stored + machine_hum.Stop(); //stop the sound effects + charge_up.Stop(); + OpenPodAnimPlaying = false; + ThawWindowAnimPlaying = false; + ThawStepInProgress = 0; + ProtoCrewMember kerbal = null; + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Crew.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == ThawKerbal) + kerbal = enumerator.Current; + } + if (!RemoveKerbal(kerbal, ToThawKerbalSeat)) // remove the CrewMember from the part, because they are frozen, and this is the only way to trick the game. + { + Debug.Log("ThawKerbalAbort Procedure FAILED! Critical error"); + } + //this.part.RemoveCrewmember(kerbal); + kerbal.type = ProtoCrewMember.KerbalType.Unowned; + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; + seatTakenbyFrznKerbal[ToThawKerbalSeat] = true; + if (vesselisinIVA || vesselisinInternal) + { + setIVAFrzrCam(ToThawKerbalSeat); + } + if (partHasInternals) + { + if (isPartAnimated) + closeCryopod(ToThawKerbalSeat, float.MaxValue); + // Utilities.Log_Debug("Time freezewindow started " + Planetarium.GetUniversalTime()); + freezeCryopodWindow(ToThawKerbalSeat, float.MaxValue); + // Utilities.Log_Debug("Time freezewindow finished make them invisible " + Planetarium.GetUniversalTime()); + cryopodstateclosed[ToThawKerbalSeat] = true; + savecryopodstatepersistent(); + if (partHasStripLights && DeepFreeze.Instance.DFsettings.StripLightsActive) + { + stopStripLightFlash(ToThawKerbalSeat); + } + } + //Make them invisible again + Utilities.setFrznKerbalLayer(part, kerbal, false); + if (ThawMsg != null) ScreenMessages.RemoveMessage(ThawMsg); + CrewHatchController.fetch.EnableInterface(); + if (DFGameEvents.onKerbalThawAbort != null) + { + DFGameEvents.onKerbalThawAbort.Fire(this.part, ThawKerbal); + } + Utilities.Log_Debug("ThawkerbalAbort End"); + } + + private void ThawKerbalStep4(String frozenkerbal) + { + Utilities.Log_Debug("ThawKerbalConfirm start for " + frozenkerbal); + machine_hum.Stop(); //stop sound effects + StoredCharge = 0; // Discharge all EC stored + + ProtoCrewMember kerbal = null; + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Crew.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == frozenkerbal) + kerbal = enumerator.Current; + } + enumerator.Dispose(); + if (!AddKerbal(kerbal, ToThawKerbalSeat)) + { + ThawKerbalAbort(frozenkerbal); + return; + } + if (partHasStripLights && DeepFreeze.Instance.DFsettings.StripLightsActive) + { + stopStripLightFlash(ToThawKerbalSeat); + } + foreach (Animator anim in kerbal.KerbalRef.gameObject.GetComponentsInChildren()) + { + if (anim.name == "kbIVA@idle") + { + Utilities.Log_Debug("Animator " + anim.name + " for " + kerbal.KerbalRef.name + " turned off"); + anim.enabled = false; + } + } + ToThawKerbal = ""; // Set the Active Thaw Kerbal to null + IsThawActive = false; // Turn the Freezer actively thawing mode off + OnATPPodSettingChanged(this.part, "A"); + ThawStepInProgress = 0; + skipThawStep1 = false; + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00102", frozenkerbal), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00102 = <<1>> thawed out + if (emergencyThawInProgress) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00103", frozenkerbal), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00103 = <<1>> was thawed out due to lack of Electrical Charge to run cryogenics + Debug.Log("DeepFreezer - kerbal " + frozenkerbal + " was thawed out due to lack of Electrical charge to run cryogenics"); + DeepFreeze.Instance.setComatoseKerbal(part, kerbal, ProtoCrewMember.KerbalType.Tourist, true); + + // Update the saved frozen kerbals dictionary + KerbalInfo kerbalInfo = new KerbalInfo(Planetarium.GetUniversalTime()); + kerbalInfo.vesselID = CrntVslID; + kerbalInfo.vesselName = CrntVslName; + kerbalInfo.experienceTraitName = kerbal.experienceTrait.Title; + kerbalInfo.type = ProtoCrewMember.KerbalType.Tourist; + kerbalInfo.status = ProtoCrewMember.RosterStatus.Assigned; + if (partHasInternals) + { + kerbalInfo.seatName = ToFrzeKerbalXformNme; + kerbalInfo.seatIdx = ToFrzeKerbalSeat; + } + else + { + kerbalInfo.seatName = "Unknown"; + kerbalInfo.seatIdx = -1; + } + kerbalInfo.partID = CrntPartID; + Utilities.Log_Debug("Adding New Comatose Crew to dictionary"); + try + { + if (!DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.ContainsKey(kerbal.name)) + { + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Add(kerbal.name, kerbalInfo); + } + if (DeepFreeze.Instance.DFsettings.debugging) DeepFreeze.Instance.DFgameSettings.DmpKnownFznKerbals(); + } + catch (Exception ex) + { + Utilities.Log("Unable to add to knownfrozenkerbals comatose crewmember " + kerbal.name); + Utilities.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00104"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00104 = DeepFreezer mechanical failure + } + } + Debug.Log("Thawed out: " + frozenkerbal); + UpdateCounts(); // Update the Crew counts + removeThawEvent(frozenkerbal); // Remove the Thaw Event for this kerbal. + if (DeepFreeze.Instance.DFsettings.OtherSoundsActive) + ding_ding.Play(); + OpenPodAnimPlaying = false; + if (DFInstalledMods.IskerbalismInstalled) // IF Kerbalism Installed, add tracking. + { + Utilities.Log_Debug("kerbalism installed track kerbal=" + frozenkerbal); + try + { + KBDisableKerbal(frozenkerbal, false); + } + catch (Exception ex) + { + Utilities.Log("DeepFreeze Exception attempting to track a kerbal in Kerbalism. Report this error on the Forum Thread."); + Utilities.Log("DeepFreeze Err: " + ex); + } + } + CrewHatchController.fetch.EnableInterface(); + DFGameEvents.onKerbalThaw.Fire(this.part, kerbal); + GameEvents.onVesselWasModified.Fire(vessel); + Utilities.Log_Debug("ThawKerbalConfirm End"); + } + + #endregion ThwKerbals + + private bool RemoveKerbal(ProtoCrewMember kerbal, int SeatIndx) + //Removes a frozen kerbal from the vessel. + { + try + { + Utilities.Log_Debug("RemoveKerbal " + kerbal.name + " seat " + SeatIndx); + FrznCrewMbr tmpcrew = null; + List.Enumerator enumerator = _StoredCrewList.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.CrewName == kerbal.name) + tmpcrew = enumerator.Current; + } + if (tmpcrew == null) + { + FrznCrewMbr frzncrew = new FrznCrewMbr(kerbal.name, SeatIndx, vessel.id, vessel.name); + Utilities.Log_Debug("Adding _StoredCrewList entry"); + _StoredCrewList.Add(frzncrew); + } + else + { + Utilities.Log("Found Kerbal in the stored frozen crew list for this part."); + Utilities.Log("Crewmember:" + tmpcrew.CrewName + " Seat:" + tmpcrew.SeatIdx); + } + // Update the saved frozen kerbals dictionary + KerbalInfo kerbalInfo = new KerbalInfo(Planetarium.GetUniversalTime()); + kerbalInfo.vesselID = CrntVslID; + kerbalInfo.vesselName = CrntVslName; + kerbalInfo.type = ProtoCrewMember.KerbalType.Unowned; + kerbalInfo.status = ProtoCrewMember.RosterStatus.Dead; + if (partHasInternals) + { + kerbalInfo.seatName = part.internalModel.seats[SeatIndx].seatTransformName; + kerbalInfo.seatIdx = SeatIndx; + } + else + { + kerbalInfo.seatName = "Unknown"; + kerbalInfo.seatIdx = -1; + } + kerbalInfo.partID = CrntPartID; + kerbalInfo.experienceTraitName = kerbal.experienceTrait.Title; + Utilities.Log_Debug("Adding New Frozen Crew to dictionary"); + try + { + if (!DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.ContainsKey(kerbal.name)) + { + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Add(kerbal.name, kerbalInfo); + } + if (DeepFreeze.Instance.DFsettings.debugging) DeepFreeze.Instance.DFgameSettings.DmpKnownFznKerbals(); + } + catch (Exception ex) + { + Utilities.Log("Unable to add to knownfrozenkerbals frozen crewmember " + kerbal.name); + Utilities.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00104"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00104 = DeepFreezer mechanical failure + return false; + } + if (partHasInternals && ExternalDoorActive) + Utilities.setHelmetshaders(kerbal.KerbalRef, true); + // remove the CrewMember from the part crewlist and unregister their traits, because they are frozen, and this is the only way to trick the game. + kerbal.UnregisterExperienceTraits(part); + part.protoModuleCrew.Remove(kerbal); + Vessel.CrewWasModified(vessel); + if (partHasInternals) + { + if (part.internalModel.seats[SeatIndx].kerbalRef != kerbal.KerbalRef) + { + part.internalModel.seats[SeatIndx].kerbalRef = kerbal.KerbalRef; + setseatstaticoverlay(part.internalModel.seats[SeatIndx]); + } + part.internalModel.seats[SeatIndx].taken = true; // Set their seat to Taken, because they are really still there. :) + seatTakenbyFrznKerbal[SeatIndx] = true; + } + // Set our newly frozen Popsicle, er Kerbal, to Unowned type (usually a Crew) and Dead status. + kerbal.type = ProtoCrewMember.KerbalType.Unowned; + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; + if (kerbal.KerbalRef != null) + { + //Remove them from the GUIManager Portrait cams. + DFPortraits.DestroyPortrait(kerbal.KerbalRef); + } + return true; + } + catch (Exception ex) + { + Debug.Log("Remove Kerbal " + kerbal.name + " for DeepFreeze failed"); + Debug.Log("Err: " + ex); + return false; + } + } + + private bool AddKerbal(ProtoCrewMember kerbal, int SeatIndx) + //Adds a just thawed kerbal to the vessel. + { + Utilities.Log_Debug("Start AddKerbal " + kerbal.name); + ProtoCrewMember.KerbalType originaltype = ProtoCrewMember.KerbalType.Crew; + try + { + try + { + FrznCrewMbr tmpcrew = null; // Find the thawed kerbal in the frozen kerbal list. + List.Enumerator enumerator = _StoredCrewList.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.CrewName == kerbal.name) + tmpcrew = enumerator.Current; + } + if (tmpcrew != null) + { + Utilities.Log_Debug("Removing _StoredCrewList entry"); + _StoredCrewList.Remove(tmpcrew); + } + } + catch (Exception ex) + { + Utilities.Log("Unable to remove _StoredCrewList frozen crewmember " + kerbal.name); + Utilities.Log("Err: " + ex); + //ScreenMessages.PostScreenMessage("DeepFreezer mechanical failure", 5.0f, ScreenMessageStyle.UPPER_CENTER); + //return false; + } + + // Update the saved frozen kerbals dictionary + Utilities.Log_Debug("Removing Frozen Crew to dictionary"); + try + { + if (DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.ContainsKey(kerbal.name)) + { + KerbalInfo tmpFrzCrew = DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals[kerbal.name]; + if (tmpFrzCrew.experienceTraitName == "Tourist") + { + originaltype = ProtoCrewMember.KerbalType.Tourist; + } + DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(kerbal.name); + } + if (DeepFreeze.Instance.DFsettings.debugging) DeepFreeze.Instance.DFgameSettings.DmpKnownFznKerbals(); + } + catch (Exception ex) + { + Utilities.Log("Unable to remove knownfrozenkerbals frozen crewmember " + kerbal.name); + Utilities.Log("Err: " + ex); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00104"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00104 = DeepFreezer mechanical failure + return false; + } + if (partHasInternals && ExternalDoorActive) + Utilities.setHelmetshaders(kerbal.KerbalRef, true); + + // Set our newly thawed Popsicle, er Kerbal, to Original type and Assigned status. + kerbal.type = originaltype; + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; + + if (partHasInternals) + { + if (kerbal.seat != part.internalModel.seats[SeatIndx]) + { + kerbal.seat = part.internalModel.seats[SeatIndx]; + kerbal.seatIdx = SeatIndx; + } + if (part.internalModel.seats[SeatIndx].crew != kerbal) + { + part.internalModel.seats[SeatIndx].crew = kerbal; + } + if (part.internalModel.seats[SeatIndx].kerbalRef != kerbal.KerbalRef) + { + part.internalModel.seats[SeatIndx].kerbalRef = kerbal.KerbalRef; + part.internalModel.seats[SeatIndx].taken = true; + setseatstaticoverlay(part.internalModel.seats[SeatIndx]); + } + seatTakenbyFrznKerbal[SeatIndx] = false; + } + + // add the CrewMember to the part crewlist and register their traits. + kerbal.RegisterExperienceTraits(part); + if (!part.protoModuleCrew.Contains(kerbal)) + { + part.protoModuleCrew.Add(kerbal); + Vessel.CrewWasModified(vessel); + } + + /*if (kerbal.KerbalRef != null) + { + if (kerbal.KerbalRef.InPart == null) + { + kerbal.KerbalRef.InPart = part; + } + //Add themto the GUIManager Portrait cams. + Portraits.RestorePortrait(kerbal.KerbalRef); + }*/ + Utilities.Log_Debug("End AddKerbal"); + return true; + } + catch (Exception ex) + { + Debug.Log("Add Kerbal " + kerbal.name + " for DeepFreeze failed"); + Debug.Log("Err: " + ex); + return false; + } + } + + internal void checkPortraitRegistered(Kerbal kerbal) + { + if (!DFPortraits.HasPortrait(kerbal, true)) + { + vessel.DespawnCrew(); + base.StartCoroutine(CallbackUtil.DelayedCallback(3, new Callback(this.delayedSpawnCrew))); + } + } + + #region CrewXfers + + internal bool IsCrewXferRunning + { + get + { + if (CrewHatchController.fetch.Active) + return true; + + if (DFInstalledMods.IsSMInstalled) + { + if (IsSMXferRunning) + return true; + } + return false; + } + } + + //This region contains the methods for handling Crew Transfers correctly + internal bool IsSMXferRunning // Checks if Ship Manifest is running a CrewXfer or Not. + { + get + { + try + { + + if (!SMWrapper.SMAPIReady) + SMWrapper.InitSMWrapper(); + if (SMWrapper.ShipManifestAPI.CrewXferActive && + (SMWrapper.ShipManifestAPI.FromPart == part || SMWrapper.ShipManifestAPI.ToPart == part)) + { + Utilities.Log_Debug("DeepFreeze SMXfer running and it is from or to this part"); + return true; + } + if (SMWrapper.ShipManifestAPI.CrewXferActive) + { + Utilities.Log_Debug("DeepFreeze SMXfer running but is it not from or to this part"); + } + return false; + } + catch (Exception ex) + { + Utilities.Log( + "DeepFreezer Error attempting to check Ship Manifest if there is a crew transfer active"); + Utilities.Log(ex.Message); + return false; + } + } + } + + /// + /// Fired when a stock crew transfer is started by gameevent onCrewTransferPartListCreated + /// Checks if This Freezer part is in the list and if it is, check if it is full or not taking into account frozen kerbal. + /// If it is move it from the OK list to the NOT OK list so the user can't select this part. + /// + /// List, List> fromToAction two lists of parts. + private void onCrewTransferPartListCreated(GameEvents.HostedFromToAction> HostedFromTo) + { + CrewMoveList.Clear(); + foreach (Part p in HostedFromTo.from) + { + if (p == part && PartFull) + { + CrewMoveList.Add(p); + } + } + + CrewMoveList.ForEach(id => HostedFromTo.from.Remove(id)); + CrewMoveList.ForEach(id => HostedFromTo.to.Add(id)); + crewTransferInputLock = true; + } + + //Delayed corountine to fire an internal onvesselchange, this forces the portraits system to refresh + internal void fireOnVesselChange() + { + onvslchgInternal = true; + GameEvents.onVesselChange.Fire(vessel); + } + + //For crew Xfer borked by a full freezer and we transfer them back we have to spawn the vessel crew then fire the onvesselchange to get the + // portraits system to refresh + internal void delayedSpawnCrew() + { + vessel.SpawnCrew(); + resetFrozenKerbals(); + fireOnVesselChange(); + } + + // this is called when a vessel change event fires. + // Triggered when switching to a different vessel, loading a vessel, or launching + private void OnVesselChange(Vessel vessel) + { + Debug.Log("DeepFreezer OnVesselChange onvslchgInternal " + onvslchgInternal + " activevessel " + FlightGlobals.ActiveVessel.id + " parametervesselid " + vessel.id + " this vesselid " + this.vessel.id + " this partid " + part.flightID); + if (onvslchgInternal) + { + onvslchgInternal = false; + return; + } + //Check a Freeze or Thaw is not in progress, if it is, we must abort. + if (IsThawActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00105"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00105 = Vessel about to change, Aborting Thaw process + Utilities.Log_Debug("Thawisactive - abort"); + ThawKerbalAbort(ToThawKerbal); + } + if (IsFreezeActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00106"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00106 = Vessel about to change, Aborting Freeze process + Utilities.Log_Debug("Freezeisactive - abort"); + FreezeKerbalAbort(ActiveFrzKerbal); + } + //If the vessel we have changed to is the same as the vessel this partmodule is attached to we LOAD persistent vars, otherwise we SAVE persistent vars. + if (vessel.id == this.vessel.id) + { + loadcryopodstatepersistent(); + loadexternaldoorstatepersistent(); + if (ExternalDoorActive) + { + setHelmetstoDoorState(); + setDoorHandletoDoorState(); + } + resetFrozenKerbals(); + if (partHasInternals) + resetCryopods(true); + } + else + { + savecryopodstatepersistent(); + saveexternaldoorstatepersistent(); + if (mon_beep != null && mon_beep.isPlaying) + { + mon_beep.Stop(); + } + } + crewTransferInputLock = false; + } + + // this is called when the vessel comes off rails. + private void onVesselGoOffRails(Vessel vessel) + { + if (vessel == this.vessel) + { + timeLoadedOffrails = Planetarium.GetUniversalTime(); + } + } + + // when the camera mode changes reset the frozen kerbal portrait cams. + private void OnCameraChange(CameraManager.CameraMode cammode) + { + resetFrozenPortraits(); + } + + // this is called when vessel is destroyed. + // Triggered when a vessel instance is destroyed; any time a vessel is unloaded, + // ie scene changes, exiting loading distance + private void onVesselDestroy(Vessel vessel) + { + Utilities.Log_Debug("OnVesselDestroy"); + //Check a Freeze or Thaw is not in progress, if it is, we must abort. + if (IsThawActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00105"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00105 = Vessel about to change, Aborting Thaw process + Utilities.Log_Debug("Thawisactive - abort"); + ThawKerbalAbort(ToThawKerbal); + } + if (IsFreezeActive) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00106"), 5.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00106 = Vessel about to change, Aborting Freeze process + Utilities.Log_Debug("Freezeisactive - abort"); + FreezeKerbalAbort(ActiveFrzKerbal); + } + } + + /// + /// This Method will get a list of all frozen kerbals in this part and remove their Portrait Cameras from the PortraitGallery if there is one. + /// It is called when GameEvent OnCameraChange is fired. + /// + internal void resetFrozenPortraits() + { + if (DeepFreeze.Instance == null || DeepFreeze.Instance.DFgameSettings == null || DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals == null) + { + return; + } + // create a list of kerbal that are in this part in this vessel & they are not comatose/tourist + List> FrznKerbalsinPart = new List>(); + foreach (var frznKerbal in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) + { + if (frznKerbal.Value.partID == CrntPartID && frznKerbal.Value.vesselID == CrntVslID && + frznKerbal.Value.type != ProtoCrewMember.KerbalType.Tourist) + { + FrznKerbalsinPart.Add(frznKerbal); + } + } + for (int i = 0; i < FrznKerbalsinPart.Count; i++) + { + ProtoCrewMember crewmember = null; + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Unowned.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == FrznKerbalsinPart[i].Key) + crewmember = enumerator.Current; + } + if (crewmember != null) + { + DFPortraits.DestroyPortrait(crewmember.KerbalRef); + } + } + } + + internal void resetFrozenKerbals() + { + try + { + // Create a list of kerbals that are in Invalid Seats (SeatIndx == -1 where kerbal is in this part in this vessel & they are not comatose/tourist + List> kerbalsInvSeats = new List>(); + foreach (var frznKerbal in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) + { + if (frznKerbal.Value.partID == CrntPartID && frznKerbal.Value.vesselID == CrntVslID && + frznKerbal.Value.type != ProtoCrewMember.KerbalType.Tourist && frznKerbal.Value.seatIdx == -1) + { + kerbalsInvSeats.Add(frznKerbal); + } + } + + // create a list of kerbal that are in this part in this vessel & they are not comatose/tourist + List> FrznKerbalsinPart = new List>(); + foreach (var frznKerbal in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) + { + if (frznKerbal.Value.partID == CrntPartID && frznKerbal.Value.vesselID == CrntVslID && + frznKerbal.Value.type != ProtoCrewMember.KerbalType.Tourist) + { + FrznKerbalsinPart.Add(frznKerbal); + } + } + + //If we found any Invalid Seat assignments we need to find them empty seats + if (kerbalsInvSeats.Count > 0) + { + bool[] seatIndxs = new bool[FreezerSize]; //Create a bool array to store whether seats are taken or not + //go through all the frozen kerbals in the part that don't have invalid seats and set bool array seat index to true (taken) for each + foreach (KeyValuePair frznkerbal in FrznKerbalsinPart) + { + if (frznkerbal.Value.seatIdx > -1 && frznkerbal.Value.seatIdx < FreezerSize - 1) + seatIndxs[frznkerbal.Value.seatIdx] = true; + } + //go through all the thawed kerbals in the part and set bool array seat index to true (taken) for each + foreach (ProtoCrewMember crew in part.protoModuleCrew) + { + seatIndxs[crew.seatIdx] = true; + } + //Go through all our kerbals with invalid seats and find them an empty seat. + foreach (KeyValuePair frznkerbal in kerbalsInvSeats) + { + //Iterate for the number of seats in the part + for (int i = 0; i < FreezerSize; i++) + { + if (seatIndxs[i] == false) //If seat not already taken we take it + { + seatIndxs[i] = true; + frznkerbal.Value.seatIdx = i; + frznkerbal.Value.seatName = part.internalModel.seats[i].seatTransformName; + break; + } + } + } + } + + // Iterate through the dictionary of all known frozen kerbals where kerbal is in this part in this vessel & they are not comatose/tourist + foreach (KeyValuePair kerbal in FrznKerbalsinPart) + { + //Check if they are in the _StoredCrewList and if they aren't Add them in. + FrznCrewMbr fzncrew = new FrznCrewMbr(kerbal.Key, kerbal.Value.seatIdx, CrntVslID, CrntVslName); + FrznCrewMbr tmpcrew = null; // Find the thawed kerbal in the frozen kerbal list. + List.Enumerator enumerator2 = _StoredCrewList.GetEnumerator(); + while (enumerator2.MoveNext()) + { + if (enumerator2.Current.CrewName == kerbal.Key) + tmpcrew = enumerator2.Current; + } + + if (tmpcrew == null) + { + //add them to our storedcrewlist for this part. + Utilities.Log_Debug("DeepFreezer Adding frozen kerbal to this part storedcrewlist " + kerbal.Key); + _StoredCrewList.Add(fzncrew); + } + + //check if they are in the part and spawned, if not do so. + ProtoCrewMember crewmember = null; + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Unowned.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == kerbal.Key) + crewmember = enumerator.Current; + } + if (crewmember != null) + { + if (partHasInternals) + { + crewmember.seatIdx = kerbal.Value.seatIdx; + if (crewmember.seatIdx != -1 && crewmember.seatIdx < FreezerSize) + crewmember.seat = part.internalModel.seats[crewmember.seatIdx]; + if (crewmember.KerbalRef == null) + { + ProtoCrewMember.Spawn(crewmember); + } + crewmember.KerbalRef.transform.parent = + part.internalModel.seats[crewmember.seatIdx].seatTransform; + crewmember.KerbalRef.transform.localPosition = Vector3.zero; + crewmember.KerbalRef.transform.localRotation = Quaternion.identity; + crewmember.KerbalRef.InPart = null; + if (ExternalDoorActive) + { + //set the seat to allow helmet, this will cause the helmet to appear + crewmember.KerbalRef.showHelmet = true; + } + else + { + crewmember.KerbalRef.showHelmet = false; + crewmember.KerbalRef.ShowHelmet(false); + } + seatTakenbyFrznKerbal[crewmember.seatIdx] = true; + //setup seat and part settings for frozen kerbal. + Utilities.setFrznKerbalLayer(part, crewmember, false); + part.internalModel.seats[crewmember.seatIdx].taken = true; + part.internalModel.seats[crewmember.seatIdx].kerbalRef = crewmember.KerbalRef; + part.internalModel.seats[crewmember.seatIdx].crew = crewmember; + setseatstaticoverlay(part.internalModel.seats[crewmember.seatIdx]); + } + //Unregister their traits/abilities and remove them from the Portrait Cameras if they are there. + crewmember.UnregisterExperienceTraits(part); + part.protoModuleCrew.Remove(crewmember); + vessel.RemoveCrew(crewmember); + DFPortraits.DestroyPortrait(crewmember.KerbalRef); + } + else + { + Utilities.Log("DeepFreezer Error attempting to resetFrozenKerbal {0}, cannot find them in the Roster", kerbal.Key); + } + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreezer Error attempting to resetFrozenKerbals, Critical ERROR, Report on the forum"); + Utilities.Log(ex.Message); + } + } + + private void onCrewTransferred(GameEvents.HostedFromToAction HostedFromTo) + { + bool fromEVA = false; + for (int i = 0; i < HostedFromTo.from.Modules.Count; ++i) + { + if (HostedFromTo.from.Modules[i] as KerbalEVA) + { + fromEVA = true; + } + } + if (fromEVA && PartFull) + { + Utilities.Log_Debug("DeepFreezer EVA kerbal tried to enter a FULL Freezer part, so we kick them out"); + if (ExternalDoorActive) + { + setHelmetstoDoorState(); + setDoorHandletoDoorState(); + } + resetFrozenKerbals(); + if (partHasInternals) + { + resetCryopods(true); + } + FlightEVA.fetch.spawnEVA(HostedFromTo.host, HostedFromTo.to, HostedFromTo.to.airlock); + CameraManager.Instance.SetCameraFlight(); + } + crewTransferInputLock = false; + } + + private void OnCrewBoardVessel(GameEvents.FromToAction fromToAction) + { + Debug.Log("OnCrewBoardVessel " + vessel.id + " " + part.flightID); + } + + private void onCrewOnEva(GameEvents.FromToAction fromToAction) + { + Debug.Log("OnCrewOnEva " + vessel.id + " " + part.flightID); + } + + #endregion CrewXfers + + private void UpdateCounts() + { + // Update the part counts. + try + { + if (!IsThawActive && !IsFreezeActive) + { + FreezerSpace = FreezerSize - _StoredCrewList.Count; + TotalFrozen = _StoredCrewList.Count; + PartFull = TotalFrozen + part.protoModuleCrew.Count >= part.CrewCapacity; + //Utilities.Log_Debug("DeepFreezer UpdateCounts FreezerSpace=" + FreezerSpace + ",TotalFrozen=" + TotalFrozen + ",Partfull=" + PartFull); + // Reset the seat status for frozen crew to taken - true, because it seems to reset by something?? So better safe than sorry. + if (partHasInternals) + { + // reset seats to TAKEN for all frozen kerbals in the part, check KerbalRef is still in place or re-instantiate it and check frozen kerbals + // are not appearing in the Portrait Cameras, if they are remove them. + //Utilities.Log_Debug("DeepFreezer StoredCrewList"); + for (int i = 0; i < _StoredCrewList.Count; i++) + //{ + // foreach (FrznCrewMbr lst in _StoredCrewList) + { + part.internalModel.seats[_StoredCrewList[i].SeatIdx].taken = true; + seatTakenbyFrznKerbal[_StoredCrewList[i].SeatIdx] = true; + setCryopodWindowSpecular(_StoredCrewList[i].SeatIdx); + + ProtoCrewMember kerbal = null; + IEnumerator enumerator = HighLogic.CurrentGame.CrewRoster.Unowned.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.name == _StoredCrewList[i].CrewName) + kerbal = enumerator.Current; + } + if (kerbal == null) + { + Utilities.Log("DeepFreezer Frozen Kerbal " + _StoredCrewList[i].CrewName + " is not found in the currentgame.crewroster.unowned, this should never happen"); + } + else + { + if (kerbal.KerbalRef == null) // Check if the KerbalRef is null, as this causes issues with CrewXfers, if it is, respawn it. + { + Utilities.Log_Debug("Kerbalref = null"); + part.internalModel.seats[_StoredCrewList[i].SeatIdx].crew = kerbal; + part.internalModel.seats[_StoredCrewList[i].SeatIdx].SpawnCrew(); // This spawns the Kerbal and sets the seat.kerbalref + setseatstaticoverlay(part.internalModel.seats[_StoredCrewList[i].SeatIdx]); + kerbal.KerbalRef.InPart = null; + kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; + kerbal.type = ProtoCrewMember.KerbalType.Unowned; + } + //Remove them from the GUIManager Portrait cams. + DFPortraits.DestroyPortrait(kerbal.KerbalRef); + Utilities.setFrznKerbalLayer(part, kerbal, false); // Double check kerbal is invisible. + } + } + } + //Utilities.Log_Debug("DeepFreezer UpdateCounts end"); + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreezer Error attempting to updatePartCounts, Critical ERROR, Report on the forum"); + Utilities.Log(ex.Message); + } + } + + + #region Cryopods + + //This region contains the methods for animating the cryopod doors and turning windows on/off (if not animated) + private void loadcryopodstatepersistent() + { + if (HighLogic.LoadedSceneIsFlight) + { + try + { + var cryopodstatestring = cryopodstateclosedstring.Split(','); + for (int i = 0; i < cryopodstatestring.Length; i++) + { + Utilities.Log_Debug("parse cryopodstring " + i + " " + cryopodstatestring[i]); + if (cryopodstatestring[i] != string.Empty) + { + cryopodstateclosed[i] = bool.Parse(cryopodstatestring[i]); + } + } + //Debug.Log("Load cryopodstatepersistent value " + cryopodstateclosedstring); + } + catch (Exception ex) + { + Debug.Log("Exception OnLoad of cryopod state string"); + Debug.Log("Err: " + ex); + } + } + } + + private void savecryopodstatepersistent() + { + if (HighLogic.LoadedSceneIsFlight && Time.timeSinceLevelLoad > 3f) + { + try + { + cryopodstateclosedstring = string.Empty; + string[] tmpCryopodstateclosedarray = new string[cryopodstateclosed.Length]; + for (int i = 0; i < cryopodstateclosed.Length; i++) + { + tmpCryopodstateclosedarray[i] = cryopodstateclosed[i].ToString(); + } + cryopodstateclosedstring = string.Join(", ", tmpCryopodstateclosedarray); + //Debug.Log("Save cryopodstatepersistent value " + cryopodstateclosedstring); + } + catch (Exception ex) + { + Debug.Log("Exception OnSave of cryopod state string"); + Debug.Log("Err: " + ex); + } + } + } + + public void resetCryopods(bool resetall) + { + try + { + // If resetall is true we check the last time a resetall was done, if it is within cryopodREsettimeDelay seconds + // we skip this resetcryopods call (so we don't see flickering). + //Otherwise we set all cryopodstatclosed to true which will force processing further down to open pods that + // may already be open , regardless. + if (resetall) + { + double currenttime = Planetarium.GetUniversalTime(); + if (currenttime - cryopodResetTime < DeepFreeze.Instance.DFsettings.cryopodResettimeDelay) + { + Utilities.Log_Debug("Last cryopod resetall occurred at: " + cryopodResetTime + " currenttime: " + currenttime + " is less than " + DeepFreeze.Instance.DFsettings.cryopodResettimeDelay + " secs ago, Ignoring request."); + return; + } + cryopodResetTime = currenttime; + for (int i = 0; i < FreezerSize; i++) + { + cryopodstateclosed[i] = true; + } + } + + //Create a temporary array and set entries to true where that seat index contains a frozen kerbal. + bool[] closedpods = new bool[FreezerSize]; + foreach (FrznCrewMbr frzncrew in _StoredCrewList) + { + closedpods[frzncrew.SeatIdx] = true; + } + //Iterate through the closedpods array. If true (frozen kerbal in this pod) we check the state of the pod + // is closed already or not. If it is not closed we close it. + // If false (no frozen kerbal in this pod) we check the state of the pod is closed already or not. + // If it is closed we open it. + for (int i = 0; i < closedpods.Length; i++) + { + Utilities.Log_Debug("resetCryopod " + i + " contains frozen kerbal? " + closedpods[i]); + if (closedpods[i]) //Pod contains a frozen kerbal + { + if (!cryopodstateclosed[i]) //If we think the pod is not closed, we close it. + { + Utilities.Log_Debug("pod is open so close it"); + if (isPartAnimated) + closeCryopod(i, float.MaxValue); + cryopodstateclosed[i] = true; + freezeCryopodWindow(i, float.MaxValue); + } + else + { + Utilities.Log_Debug("pod is already closed"); + freezeCryopodWindow(i, float.MaxValue); + } + } + else //Pod does not contain a frozen kerbal + { + if (cryopodstateclosed[i]) //If we think the pod is closed, we open it. + { + Utilities.Log_Debug("pod is closed so open it"); + if (isPartAnimated) + { + openCryopod(i, float.MaxValue); + } + if (isPartAnimated || (isPodExternal && DFInstalledMods.IsJSITransparentPodsInstalled && _prevRPMTransparentpodSetting == "ON")) + thawCryopodWindow(i, float.MaxValue); + cryopodstateclosed[i] = false; + } + else + { + Utilities.Log_Debug("pod is already open"); + if (isPartAnimated || (isPodExternal && DFInstalledMods.IsJSITransparentPodsInstalled && _prevRPMTransparentpodSetting == "ON")) + thawCryopodWindow(i, float.MaxValue); + } + } + setseatstaticoverlay(part.internalModel.seats[i]); + } + savecryopodstatepersistent(); + } + catch (Exception ex) + { + Debug.Log("Unable to reset cryopods in internal model for " + part.vessel.id + " " + part.flightID); + Debug.Log("Err: " + ex); + } + } + + private void openCryopod(int seatIndx, float speed) //only called for animated internal parts + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + Utilities.Log_Debug("playing animation opencryopod " + cryopodVariables[seatIndx].podName + " " + cryopodVariables[seatIndx].windowName); + try + { + if (cryopodVariables[seatIndx].podAnimation != null) + { + if (cryopodstateclosed[seatIndx]) + { + cryopodVariables[seatIndx].podAnimation["Open"].speed = speed; + cryopodVariables[seatIndx].podAnimation.Play("Open"); + cryopodstateclosed[seatIndx] = false; + savecryopodstatepersistent(); + } + } + else + Utilities.Log_Debug("animation not found"); + } + catch (Exception ex) + { + Debug.Log("Unable to find animation in internal model for this part called " + cryopodVariables[seatIndx].podName); + Debug.Log("Err: " + ex); + } + } + + private void thawCryopodWindow(int seatIndx, float speed) + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + setCryopodWindowOpaque(seatIndx); + + if (isPodExternal) + { + External_Window_Occluder = Utilities.SetInternalDepthMask(part, true, "External_Window_Occluder", External_Window_Occluder); //Set window occluder off + if (External_Window_Occluder_Renderer != null && External_Window_Material_Depth != null && External_Window_Material_Ice != null) + { + External_Window_Occluder_Renderer.material = External_Window_Material_Ice; + Color extsavedwindowcolor = External_Window_Occluder_Renderer.material.color; + extsavedwindowcolor.a = 1.0f; + External_Window_Occluder_Renderer.material.color = extsavedwindowcolor; + } + } + + if (cryopodVariables[seatIndx].windowAnimation == null) + { + if (!isPodExternal) + { + Utilities.Log_Debug("Why can't I find the window animation?"); + } + } + else + { + cryopodVariables[seatIndx].windowAnimation["CryopodWindowOpen"].speed = speed; + cryopodVariables[seatIndx].windowAnimation.Play("CryopodWindowOpen"); + } + if (isPodExternal && cryopodVariables[seatIndx].extwindowAnimation != null) + { + cryopodVariables[seatIndx].extwindowAnimation["CryopodWindowOpen"].speed = speed; + cryopodVariables[seatIndx].extwindowAnimation.Play("CryopodWindowOpen"); + } + if (isPodExternal && External_Window_Occluder_Anim != null) + { + External_Window_Occluder_Anim["CryopodWindowOpen"].speed = speed; + External_Window_Occluder_Anim.Play("CryopodWindowOpen"); + } + } + + private void setCryopodWindowOpaque(int seatIndx) + { + try + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + //Set their Window glass to fully opaque. - Just in case. + if (cryopodVariables[seatIndx].intwindowRenderer != null) + { + cryopodVariables[seatIndx].intwindowRenderer.material.shader = TransparentSpecularShader; + Color savedwindowcolor = cryopodVariables[seatIndx].intwindowRenderer.material.color; + savedwindowcolor.a = 1f; + cryopodVariables[seatIndx].intwindowRenderer.material.color = savedwindowcolor; + } + if (isPodExternal) + { + if (cryopodVariables[seatIndx].extwindowRenderer != null) + { + cryopodVariables[seatIndx].extwindowRenderer.material.shader = TransparentSpecularShader; + Color extsavedwindowcolor = cryopodVariables[seatIndx].extwindowRenderer.material.color; + extsavedwindowcolor.a = 1f; + cryopodVariables[seatIndx].extwindowRenderer.material.color = extsavedwindowcolor; + } + } + } + catch (Exception ex) + { + Debug.Log("Unable to setCryopodWindowOpaque seat " + seatIndx); + Debug.Log("Err: " + ex); + } + } + + private void setCryopodWindowSpecular(int seatIndx) + { + try + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + //Set the window glass to specular shader + if (cryopodVariables[seatIndx].intwindowRenderer != null) + { + if (cryopodVariables[seatIndx].intwindowRenderer.material.shader != KSPSpecularShader) + cryopodVariables[seatIndx].intwindowRenderer.material.shader = KSPSpecularShader; + } + + if (isPodExternal && cryopodVariables[seatIndx].extwindowRenderer != null) + { + if (cryopodVariables[seatIndx].extwindowRenderer.material.shader != KSPSpecularShader) + cryopodVariables[seatIndx].extwindowRenderer.material.shader = KSPSpecularShader; + } + } + catch (Exception ex) + { + Debug.Log("Unable to setCryopodWindowSpecular seat " + seatIndx); + Debug.Log("Err: " + ex); + } + } + + private void startStripLightFlash(int seatIndx) + { + // Utilities.Log_Debug("playing animation PodActive " + stripName); + try + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + if (cryopodVariables[seatIndx].stripAnimation != null) + { + cryopodVariables[seatIndx].stripAnimation.Stop(); + cryopodVariables[seatIndx].stripAnimation["PodActive"].speed = 1; + cryopodVariables[seatIndx].stripAnimation["PodActive"].normalizedTime = 0; + cryopodVariables[seatIndx].stripAnimation.wrapMode = WrapMode.Loop; + cryopodVariables[seatIndx].stripAnimation.Play("PodActive"); + } + else + { + Utilities.Log_Debug("animation PodActive not found for " + cryopodVariables[seatIndx].stripName); + } + } + catch (Exception ex) + { + Debug.Log("Unable to run lightstrip animations in internal model for this part called " + cryopodVariables[seatIndx].stripName); + Debug.Log("Err: " + ex); + } + } + + private void closeCryopod(int seatIndx, float speed) //only called for animated internal parts + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + Utilities.Log_Debug("playing animation closecryopod " + cryopodVariables[seatIndx].podName + " " + cryopodVariables[seatIndx].windowName); + try + { + if (cryopodVariables[seatIndx].podAnimation != null) + { + if (!cryopodstateclosed[seatIndx]) + { + cryopodVariables[seatIndx].podAnimation["Close"].speed = speed; + cryopodVariables[seatIndx].podAnimation.Play("Close"); + cryopodstateclosed[seatIndx] = true; + savecryopodstatepersistent(); + } + } + else + Utilities.Log_Debug("Cryopod animation not found"); + } + catch (Exception ex) + { + Debug.Log("Unable to find animation in internal model for this part called " + cryopodVariables[seatIndx].podName); + Debug.Log("Err: " + ex); + } + } + + private void freezeCryopodWindow(int seatIndx, float speed) + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + if (isPartAnimated || (isPodExternal && DFInstalledMods.IsJSITransparentPodsInstalled && _prevRPMTransparentpodSetting == "ON")) + { + setCryopodWindowTransparent(seatIndx); + } + else + { + speed = float.MaxValue; + } + + if (isPodExternal) + { + External_Window_Occluder = Utilities.SetInternalDepthMask(part, true, "External_Window_Occluder"); //Set window occluder visible (block internals) + if (External_Window_Occluder_Renderer != null && External_Window_Material_Depth != null && External_Window_Material_Ice != null) + { + External_Window_Occluder_Renderer.material = External_Window_Material_Ice; + Color extsavedwindowcolor = External_Window_Occluder_Renderer.material.color; + extsavedwindowcolor.a = 0.3f; + External_Window_Occluder_Renderer.material.color = extsavedwindowcolor; + } + } + + if (cryopodVariables[seatIndx].windowAnimation == null) + { + if (!isPodExternal) + { + Utilities.Log_Debug("Why can't I find the window animation?"); + } + } + else + { + cryopodVariables[seatIndx].windowAnimation["CryopodWindowClose"].speed = speed; + cryopodVariables[seatIndx].windowAnimation.Play("CryopodWindowClose"); + } + if (isPodExternal && cryopodVariables[seatIndx].extwindowAnimation != null) + { + cryopodVariables[seatIndx].extwindowAnimation["CryopodWindowClose"].speed = speed; + cryopodVariables[seatIndx].extwindowAnimation.Play("CryopodWindowClose"); + } + if (isPodExternal && External_Window_Occluder_Anim != null) + { + External_Window_Occluder_Anim["CryopodWindowClose"].speed = speed; + External_Window_Occluder_Anim.Play("CryopodWindowClose"); + } + } + + private void setCryopodWindowTransparent(int seatIndx) + { + try + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + //Set their Window glass to see-through. - Just in case. + if (cryopodVariables[seatIndx].intwindowRenderer != null) + { + cryopodVariables[seatIndx].intwindowRenderer.material.shader = TransparentSpecularShader; + Color savedwindowcolor = cryopodVariables[seatIndx].intwindowRenderer.material.color; + savedwindowcolor.a = 0.3f; + cryopodVariables[seatIndx].intwindowRenderer.material.color = savedwindowcolor; + } + + if (isPodExternal) + { + if (cryopodVariables[seatIndx].extwindowRenderer != null) + { + cryopodVariables[seatIndx].extwindowRenderer.material.shader = TransparentSpecularShader; + Color extsavedwindowcolor = cryopodVariables[seatIndx].extwindowRenderer.material.color; + extsavedwindowcolor.a = 0.3f; + cryopodVariables[seatIndx].extwindowRenderer.material.color = extsavedwindowcolor; + } + if (External_Window_Occluder != null) + { + + } + } + } + catch (Exception ex) + { + Debug.Log("Unable to setCryopodWindowTransparent seat " + seatIndx); + Debug.Log("Err: " + ex); + } + } + + private void stopStripLightFlash(int seatIndx) + { + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + // Utilities.Log_Debug("playing animation LightStrip " + stripName); + try + { + if (cryopodVariables[seatIndx].stripAnimation != null) + { + cryopodVariables[seatIndx].stripAnimation.Stop(); + cryopodVariables[seatIndx].stripAnimation["LightStrip"].speed = 1; + cryopodVariables[seatIndx].stripAnimation["LightStrip"].normalizedTime = 0; + cryopodVariables[seatIndx].stripAnimation.wrapMode = WrapMode.Loop; + cryopodVariables[seatIndx].stripAnimation.Play("LightStrip"); + } + else + { + Utilities.Log_Debug("animation LightStrip not found for " + cryopodVariables[seatIndx].stripName); + } + } + catch (Exception ex) + { + Debug.Log("Unable to run lightstrip animations in internal model for this part called " + cryopodVariables[seatIndx].stripName); + Debug.Log("Err: " + ex); + } + } + + //This method sets the internal camera to the Freezer view prior to thawing or freezing a kerbal so we can see the nice animations. + private void setIVAFrzrCam(int seatIndx) + { + internalSeatIdx = seatIndx; + if (cryopodVariables.Count < seatIndx) + { + Utilities.Log_Debug("Cannot Find Cryopod " + seatIndx + "Animation and Renderer Data"); + return; + } + if (cryopodVariables[seatIndx].camera != null) //Found Freezer Camera so switch to it. + { + Transform camxform = cryopodVariables[seatIndx].camera.transform; + if (camxform != null) + { + CameraManager.Instance.SetCameraInternal(part.internalModel, camxform); + DFIntMemory.Instance.lastFrzrCam = seatIndx; + } + } + else //Didn't find Freezer Camera so kick out to flight camera. + { + CameraManager.Instance.SetCameraMode(CameraManager.CameraMode.Flight); + } + Utilities.Log_Debug("Finished Setting FrzrCam " + cryopodVariables[seatIndx].camName); + } + + private void setseatstaticoverlay(InternalSeat seat) + { + try + { + if (seat.kerbalRef != null) + { + seat.kerbalRef.staticOverlayDuration = 0f; + seat.kerbalRef.state = Kerbal.States.ALIVE; + } + } + catch (Exception ex) + { + Utilities.Log("DeepFreezer Error attempting to change staticoverlayduration"); + Utilities.Log(ex.Message); + } + } + + #endregion Cryopods + + #region ExternalDoor + + private IEnumerator openDoors(float speed) + { + _prevexterndoorstate = _externaldoorstate; + _externaldoorstate = DoorState.OPENING; + Events["eventOpenDoors"].active = false; + Events["eventCloseDoors"].active = false; + if (animationName != null) + { + externalDoorAnim[animationName].normalizedTime = 0; + externalDoorAnim[animationName].speed = speed; + if (externalDoorAnimOccluder != null) + { + externalDoorAnimOccluder[animationName].normalizedTime = 0; + externalDoorAnimOccluder[animationName].speed = speed; + externalDoorAnimOccluder.Play(animationName); + } + externalDoorAnim.Play(animationName); + while (externalDoorAnim.IsPlaying(animationName)) + { + yield return null; + } + //yield return Utilities.WaitForAnimation(externalDoorAnim, animationName); + } + Events["eventCloseDoors"].active = true; + _prevexterndoorstate = _externaldoorstate; + _externaldoorstate = DoorState.OPEN; + } + + private IEnumerator closeDoors(float speed) + { + _prevexterndoorstate = _externaldoorstate; + _externaldoorstate = DoorState.CLOSING; + Events["eventOpenDoors"].active = false; + Events["eventCloseDoors"].active = false; + if (animationName != null) + { + externalDoorAnim[animationName].normalizedTime = 1; + externalDoorAnim[animationName].speed = speed; + if (externalDoorAnimOccluder != null) + { + externalDoorAnimOccluder[animationName].normalizedTime = 1; + externalDoorAnimOccluder[animationName].speed = speed; + externalDoorAnimOccluder.Play(animationName); + } + externalDoorAnim.Play(animationName); + while (externalDoorAnim.IsPlaying(animationName)) + { + yield return null; + } + //yield return Utilities.WaitForAnimation(externalDoorAnim, animationName); + } + Events["eventOpenDoors"].active = true; + _prevexterndoorstate = _externaldoorstate; + _externaldoorstate = DoorState.CLOSED; + } + + private void setHelmetstoDoorState() + { + if (_externaldoorstate == DoorState.CLOSED) + { + part.setHelmets(false); + } + else + { + part.setHelmets(true); + } + } + + private void setDoorHandletoDoorState() + { + if (_externaldoorstate == DoorState.OPEN || _externaldoorstate == DoorState.OPENING) + { + try + { + Animation[] animators = part.internalModel.FindModelAnimators("DOORHandle"); + if (animators.Length > 0) + { + var anim = animators[0]; + anim["DOORHandle"].speed = float.MaxValue; + anim["DOORHandle"].normalizedTime = 0; + anim.Play("DOORHandle"); + } + } + catch (Exception ex) + { + Debug.Log("Exception trying to run the Doorhandle animation"); + Debug.Log("Err: " + ex); + } + } + } + + private void loadexternaldoorstatepersistent() + { + try + { + if (strexternaldoorstate == "OPEN") + { + _externaldoorstate = DoorState.OPEN; + } + else + { + _externaldoorstate = DoorState.CLOSED; + } + if (strprevexterndoorstate == "OPEN") + { + _prevexterndoorstate = DoorState.OPEN; + } + else + { + _prevexterndoorstate = DoorState.CLOSED; + } + } + catch (Exception ex) + { + Debug.Log("Exception OnLoad of external door state string"); + Debug.Log("Err: " + ex); + } + } + + private void saveexternaldoorstatepersistent() + { + if (HighLogic.LoadedSceneIsFlight) + { + if (_externaldoorstate == DoorState.OPEN || _externaldoorstate == DoorState.OPENING) + { + strexternaldoorstate = "OPEN"; + } + else + { + strexternaldoorstate = "CLOSED"; + } + if (_prevexterndoorstate == DoorState.OPEN || _externaldoorstate == DoorState.OPENING) + { + strprevexterndoorstate = "OPEN"; + } + else + { + strprevexterndoorstate = "CLOSED"; + } + } + else + { + strexternaldoorstate = "CLOSED"; + strprevexterndoorstate = "CLOSED"; + } + } + + private DoorState getdoorState() + { + if (externalDoorAnim != null) + { + if (externalDoorAnim[animationName].normalizedTime == 1f) //closed + { + Utilities.Log_Debug("getdoorState closed"); + return DoorState.CLOSED; + } + if (externalDoorAnim[animationName].normalizedTime == 0f) //open + { + Utilities.Log_Debug("getdoorState open"); + return DoorState.OPEN; + } + Utilities.Log_Debug("getdoorState unknown"); + return DoorState.UNKNOWN; + } + Utilities.Log_Debug("getdoorState Animation not found"); + return DoorState.UNKNOWN; + } + + #endregion ExternalDoor + + #region BackgroundProcessing + + private const String MAIN_POWER_NAME = "ElectricCharge"; + + //This method is called by the BackgroundProcessing DLL, if the user has installed it. Otherwise it will never be called. + //It will consume ElectricCharge for Freezer that contain frozen kerbals for vessels that are unloaded, if the user has turned on the ECreqdForFreezer option in the settings menu. + public static void FixedBackgroundUpdate(Vessel v, uint partFlightID, Func resourceRequest, ref Object data) + { + if (Time.timeSinceLevelLoad < 2.0f || CheatOptions.InfiniteElectricity) // Check not loading level + { + return; + } + + if (DFIntMemory.Instance && DFIntMemory.Instance.BGRinstalled) //If Background Resources mod is installed. Don't do BackgroundProcessing Mod work. + { + return; + } + bool debug = true; + try + { + debug = DeepFreeze.Instance.DFsettings.debugging; + } + catch + { + Utilities.Log("DeepFreeze FixedBackgroundUpdate failed to get debug setting"); + } + if (debug) Debug.Log("FixedBackgroundUpdate vesselID " + v.id + " partID " + partFlightID); + // If the user does not have ECreqdForFreezer option ON, then we do nothing and return + if (!DeepFreeze.Instance.DFsettings.ECreqdForFreezer) + { + //if (debug) Debug.Log("FixedBackgroundUpdate ECreqdForFreezer is OFF, nothing to do"); + return; + } + // If the vessel this module is attached to is NOT stored in the DeepFreeze dictionary of known deepfreeze vessels we can't do anything, But this should NEVER happen. + VesselInfo vslinfo; + if (!DeepFreeze.Instance.DFgameSettings.knownVessels.TryGetValue(v.id, out vslinfo)) + { + if (debug) Debug.Log("FixedBackgroundUpdate unknown vessel, cannot process"); + return; + } + //Except if there are no frozen crew on board we don't need to consume any EC + if (vslinfo.numFrznCrew == 0) + { + //if (debug) Debug.Log("FixedBackgroundUpdate No Frozen Crew on-board, nothing to do"); + return; + } + PartInfo partInfo; + if (!DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(partFlightID, out partInfo)) + { + if (debug) Debug.Log("FixedBackgroundUpdate Can't get the Freezer Part Information, so cannot process"); + return; + } + // OK now we have something to do for real. + // Calculate the time since last consumption of EC, then calculate the EC required and request it from BackgroundProcessing DLL. + // If the vessel runs out of EC the DeepFreezeGUI class will handle notifying the user, not here. + double currenttime = Planetarium.GetUniversalTime(); + if (Utilities.timewarpIsValid(5)) + { + double timeperiod = currenttime - partInfo.timeLastElectricity; + if (timeperiod >= 1f && partInfo.numFrznCrew > 0) //We have frozen Kerbals, consume EC + { + double Ecreqd = partInfo.frznChargeRequired / 60.0f * timeperiod * vslinfo.numFrznCrew; + if (debug) Debug.Log("FixedBackgroundUpdate timeperiod = " + timeperiod + " frozenkerbals onboard part = " + vslinfo.numFrznCrew + " ECreqd = " + Ecreqd); + float Ecrecvd = 0f; + Ecrecvd = resourceRequest(v, (float)Ecreqd, MAIN_POWER_NAME); + + if (debug) Debug.Log("Consumed Freezer EC " + Ecreqd + " units"); + + if (Ecrecvd >= (float)Ecreqd * 0.99) + { + if (OnGoingECMsg != null) ScreenMessages.RemoveMessage(OnGoingECMsg); + partInfo.timeLastElectricity = (float)currenttime; + partInfo.deathCounter = currenttime; + partInfo.outofEC = false; + partInfo.ECWarning = false; + vslinfo.storedEC -= Ecrecvd; + } + else + { + if (debug) Debug.Log("FixedBackgroundUpdate DeepFreezer Ran out of EC to run the freezer"); + if (!partInfo.ECWarning) + { + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00072"), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00072 = Insufficient electric charge to monitor frozen kerbals. + partInfo.ECWarning = true; + partInfo.deathCounter = currenttime; + } + if (OnGoingECMsg != null) ScreenMessages.RemoveMessage(OnGoingECMsg); + OnGoingECMsg = ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00073", (deathRoll - (currenttime - partInfo.deathCounter)).ToString("######0"))); //#autoLOC_DF_00073 = \u0020Freezer Out of EC : Systems critical in <<1>> secs + partInfo.outofEC = true; + if (debug) Debug.Log("FixedBackgroundUpdate deathCounter = " + partInfo.deathCounter); + if (currenttime - partInfo.deathCounter > deathRoll) + { + if (DeepFreeze.Instance.DFsettings.fatalOption) + { + if (debug) Debug.Log("FixedBackgroundUpdate deathRoll reached, Kerbals all die..."); + partInfo.deathCounter = currenttime; + //all kerbals dies + var kerbalsToDelete = new List(); + foreach (KeyValuePair kerbal in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) + { + if (kerbal.Value.partID == partFlightID && kerbal.Value.vesselID == v.id && kerbal.Value.type != ProtoCrewMember.KerbalType.Tourist) + { + kerbalsToDelete.Add(kerbal.Key); + } + } + foreach (string deathKerbal in kerbalsToDelete) + { + DeepFreeze.Instance.KillFrozenCrew(deathKerbal); + ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_DF_00074", deathKerbal), 10.0f, ScreenMessageStyle.UPPER_CENTER); //#autoLOC_DF_00074 = <<1>> died due to lack of Electrical Charge to run cryogenics + if (debug) Debug.Log("FixedBackgroundUpdate DeepFreezer - kerbal " + deathKerbal + " died due to lack of Electrical charge to run cryogenics"); + } + kerbalsToDelete.ForEach(id => DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(id)); + } + else //NON Fatal option - emergency thaw all kerbals. + { + // Cannot emergency thaw in background processing. It is expected that DeepFreezeGUI will pick up that EC has run out and prompt the user to switch to the vessel. + // When the user switches to the vessel the DeepFreezer partmodule will detect no EC is available and perform an emergency thaw procedure. + if (debug) Debug.Log("FixedBackgroundUpdate DeepFreezer - EC has run out non-fatal option"); + } + } + } + } + } + else //Timewarp is too high + { + if (debug) Debug.Log("FixedBackgroundUpdate Timewarp is too high to backgroundprocess"); + partInfo.deathCounter = currenttime; + partInfo.outofEC = false; + partInfo.ECWarning = false; + } + } + + #endregion BackgroundProcessing + } + +} \ No newline at end of file diff --git a/Source/EngineerReport.cs b/Source/EngineerReport.cs new file mode 100644 index 0000000..75223fd --- /dev/null +++ b/Source/EngineerReport.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using System.Linq; +using PreFlightTests; +using RSTUtils; +using KSP.Localization; + +namespace DF +{ + public class DFEngReport : DesignConcernBase + { + private ShipConstruct ship; + private List cryofreezers = new List(); + private string Glykerol = "Glykerol"; + + // Is the Test OK ? + public override bool TestCondition() + { + Utilities.Log_Debug("DFEngReport Test condition"); + ship = EditorLogic.fetch.ship; + cryofreezers.Clear(); + cryofreezers = (from p in ship.parts where p.Modules.Contains("DeepFreezer") select p).ToList(); + if (!cryofreezers.Any()) + { + //No freezer parts + Utilities.Log_Debug("DFEngReport No Freezer Parts"); + return true; + } + + //Search through the ship resources for Glykerol. + PartResourceDefinition glykerol = PartResourceLibrary.Instance.GetDefinition(Glykerol); + double glykerolOnBoard = 0; + foreach (Part part in ship.parts) + { + if (part.Resources.Contains(glykerol.id)) + { + PartResource glyk = part.Resources.Get(glykerol.id); + glykerolOnBoard += glyk.amount; + } + } + + //If we found 5 or more units of glykerol all ok. + if (glykerolOnBoard >= 5) + { + Utilities.Log_Debug("DFEngReport 5 units found"); + return true; + } + Utilities.Log_Debug("DFEngReport No Glykerol Found"); + return false; + } + + // List of affected parts + public override List GetAffectedParts() + { + return cryofreezers; + } + + // Title of the problem description + public override string GetConcernTitle() + { + return Localizer.Format("#autoLOC_DF_00003"); // "DeepFreeze"; + } + + // problem description + public override string GetConcernDescription() + { + return Localizer.Format("#autoLOC_DF_00108"); // "There is less than 5 units of Glykerol on-board for your DeepFreeze Freezers"; + } + + // how bad is the problem + public override DesignConcernSeverity GetSeverity() + { + return DesignConcernSeverity.NOTICE; + } + + // does it applies to Rocket, plane or both + public override EditorFacilities GetEditorFacilities() + { + return EditorFacilities.ALL; + } + } +} \ No newline at end of file diff --git a/Source/FrozenCrewClasses.cs b/Source/FrozenCrewClasses.cs new file mode 100644 index 0000000..8ece14a --- /dev/null +++ b/Source/FrozenCrewClasses.cs @@ -0,0 +1,49 @@ +/** + * FrozenCrewClasses.cs + * + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using System.Collections.Generic; + +namespace DF +{ + public class FrznCrewMbr + { + public string CrewName { get; set; } + public int SeatIdx { get; set; } + public Guid VesselID { get; set; } + public string VesselName { get; set; } + + public FrznCrewMbr(string crewName, int seat, Guid vessel, string VesselName) + { + CrewName = crewName; + SeatIdx = seat; + VesselID = vessel; + this.VesselName = VesselName; + } + } + + public class FrznCrewList : List + { + } + + public enum FrzrTmpStatus + { + OK = 0, + WARN = 1, + RED = 2 + } +} \ No newline at end of file diff --git a/Source/InstallChecker.cs b/Source/InstallChecker.cs new file mode 100644 index 0000000..778817c --- /dev/null +++ b/Source/InstallChecker.cs @@ -0,0 +1,131 @@ +/** + * Based on the InstallChecker from the Kethane mod for Kerbal Space Program. + * https://github.com/Majiir/Kethane/blob/b93b1171ec42b4be6c44b257ad31c7efd7ea1702/Plugin/InstallChecker.cs + * + * Original is (C) Copyright Majiir. + * CC0 Public Domain (http://creativecommons.org/publicdomain/zero/1.0/) + * http://forum.kerbalspaceprogram.com/threads/65395-CompatibilityChecker-Discussion-Thread?p=899895&viewfull=1#post899895 + * + * This file has been modified extensively and is released under the same license. + */ + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using RSTUtils; +using UnityEngine; + +namespace DF +{ + [KSPAddon(KSPAddon.Startup.MainMenu, true)] + internal class InstallChecker : MonoBehaviour + { + // This class checks DeepFreeze is installed correctly. + private const string modName = "DeepFreeze"; + + private const string expectedPath = "REPOSoftTech/DeepFreeze/Plugins"; + + protected void Start() + { + try + { + // Log some information that might be of interest when debugging + Utilities.Log(modName + " - KSPUtil.ApplicationRootPath = " + KSPUtil.ApplicationRootPath); + Utilities.Log(modName + " - GameDatabase.Instance.PluginDataFolder = " + GameDatabase.Instance.PluginDataFolder); + Utilities.Log(modName + " - Assembly.GetExecutingAssembly().Location = " + Assembly.GetExecutingAssembly().Location); + Utilities.Log(modName + " - Using 64-bit? " + (IntPtr.Size == 8)); + + // Search for this mod's DLL existing in the wrong location. This will also detect duplicate copies because only one can be in the right place. + var assemblies = AssemblyLoader.loadedAssemblies.Where(a => a.assembly.GetName().Name == Assembly.GetExecutingAssembly().GetName().Name).Where(a => a.url != expectedPath); + var loadedAssemblies = assemblies as AssemblyLoader.LoadedAssembly[] ?? assemblies.ToArray(); + if (loadedAssemblies.Any()) + { + var badPaths = loadedAssemblies.Select(a => a.path).Select(p => Uri.UnescapeDataString(new Uri(Path.GetFullPath(KSPUtil.ApplicationRootPath)).MakeRelativeUri(new Uri(p)).ToString().Replace('/', Path.DirectorySeparatorChar))); + string badPathsString = String.Join("\n", badPaths.ToArray()); + Utilities.Log(modName + " - Incorrectly installed, bad paths:\n" + badPathsString); + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "IncorrectInstallation", "Incorrect " + modName + " Installation", + modName + " has been installed incorrectly and will not function properly. All files should be located in KSP/GameData/" + expectedPath + + ". Do not move any files from inside that folder.\n\nPlease Remove all old installations and invalid files, as follows.\n\nIncorrect path(s):\n" + badPathsString, + "OK", false, HighLogic.UISkin); + + } + + // Check for Raster Prop Monitor, If installed must also have Module Manager Installed + if (AssemblyLoader.loadedAssemblies.Any(a => a.assembly.GetName().Name.StartsWith("RasterPropMonitor"))) + { + if (!AssemblyLoader.loadedAssemblies.Any(a => a.assembly.GetName().Name.StartsWith("ModuleManager") && a.url == "")) + { + Utilities.Log(modName + " - Missing or incorrectly installed RPM & ModuleManager."); + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "IncorrectInstallation", "Missing Module Manager", + modName + " requires the Module Manager mod in order to function properly with Raster Prop Monitor mod Installed.\n\nPlease download from http://forum.kerbalspaceprogram.com/threads/55219 and copy to the KSP/GameData/ directory.", + "OK", false, HighLogic.UISkin); + } + } + + /* + // Check for Module Manager + if (!AssemblyLoader.loadedAssemblies.Any(a => a.assembly.GetName().Name.StartsWith("ModuleManager") && a.url == "")) + { + Utilities.Log("DeepFreeze - Missing or incorrectly installed ModuleManager."); + PopupDialog.SpawnPopupDialog("Missing Module Manager", + modName + " requires the Module Manager mod in order to function properly.\n\nPlease download from http://forum.kerbalspaceprogram.com/threads/55219 and copy to the KSP/GameData/ directory.", + "OK", false, HighLogic.Skin); + } + */ + // Is AddonController installed? (It could potentially cause problems.) + if (AssemblyLoader.loadedAssemblies.Any(a => a.assembly.GetName().Name.StartsWith("AddonController"))) + { + Utilities.Log("AddonController is installed"); + } + + // Is Compatibility Popup Blocker installed? (It could potentially cause problems.) + if (AssemblyLoader.loadedAssemblies.Any(a => a.assembly.GetName().Name.StartsWith("popBlock"))) + { + Utilities.Log("Compatibility Popup Blocker is installed"); + } + + //CleanupOldVersions(); + } + catch (Exception ex) + { + Utilities.Log("DeepFreeze - Caught an exception:\n" + ex.Message + "\n" + ex.StackTrace); + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "IncorrectInstallation", "Incorrect " + modName + " Installation", + "A very serious error has occurred while checking the installation of " + modName + ".\n\n" + + "You need to\n" + + " (1) shut down KSP,\n" + + " (2) send a complete copy of the entire log file to the mod developer\n" + + " (3) completely delete and re-install " + modName, + "OK", false, HighLogic.UISkin); + } + } + + /* + * Tries to fix the install if it was installed over the top of a previous version + */ + + private void CleanupOldVersions() + { + /* + bool requireRestart = false; + + // Upgrading 14.3 -> 15.0 + // Moved into new directory for REPOSoftTech Forked version. + // Was GameData/PaladinLabs now GameData/REPOSoftTech + if (File.Exists(KSPUtil.ApplicationRootPath + "x.cfg")) + { + Utilities.Log(modName + " - deleting the old x.cfg."); + File.Delete(KSPUtil.ApplicationRootPath + "x.cfg"); + requireRestart = true; + } + + if (requireRestart) + { + Utilities.Log(modName + " - requiring restart."); + PopupDialog.SpawnPopupDialog("Incorrect " + modName + " Installation", + "Files from a previous version of " + modName + " were found and deleted. You need to restart KSP now.", + "OK", false, HighLogic.Skin); + }*/ + } + } +} \ No newline at end of file diff --git a/Source/KerbalInfo.cs b/Source/KerbalInfo.cs new file mode 100644 index 0000000..87dcfaa --- /dev/null +++ b/Source/KerbalInfo.cs @@ -0,0 +1,147 @@ +/** + * KerbalInfo.cs + * + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ + +using System; +using UnityEngine; + +namespace DF +{ + public class KerbalInfo + { + public const string ConfigNodeName = "KerbalInfo"; + + public double lastUpdate; + public ProtoCrewMember.RosterStatus status; + public ProtoCrewMember.KerbalType type; + public Guid vesselID; + public string vesselName; + public uint partID; + public int seatIdx; + public string seatName; + public string experienceTraitName; + + public KerbalInfo(double currentTime) + { + lastUpdate = currentTime; + } + + public static KerbalInfo Load(ConfigNode node) + { + double lastUpdate = GetNodeValue(node, "lastUpdate", 0.0); + + KerbalInfo info = new KerbalInfo(lastUpdate); + info.status = GetNodeValue(node, "status", ProtoCrewMember.RosterStatus.Dead); + info.type = GetNodeValue(node, "type", ProtoCrewMember.KerbalType.Unowned); + string tmpvesselID = GetNodeValue(node, "vesselID", ""); + + try + { + info.vesselID = new Guid(tmpvesselID); + } + catch (Exception ex) + { + info.vesselID = Guid.Empty; + Debug.Log("DFInterface - Load of GUID VesselID for frozen kerbal failed Err: " + ex); + } + info.partID = GetNodeValue(node, "partID", (uint)0); + info.vesselName = GetNodeValue(node, "VesselName", " "); + info.seatIdx = GetNodeValue(node, "seatIdx", 0); + info.seatName = GetNodeValue(node, "seatName", ""); + info.experienceTraitName = GetNodeValue(node, "experienceTraitName", " "); + + return info; + } + + public ConfigNode Save(ConfigNode config) + { + ConfigNode node = config.AddNode(ConfigNodeName); + node.AddValue("lastUpdate", lastUpdate); + node.AddValue("status", status); + node.AddValue("type", type); + node.AddValue("vesselID", vesselID); + node.AddValue("VesselName", vesselName); + node.AddValue("partID", partID); + node.AddValue("seatIdx", seatIdx); + node.AddValue("seatName", seatName); + node.AddValue("experienceTraitName", experienceTraitName); + + return node; + } + + public static int GetNodeValue(ConfigNode confignode, string fieldname, int defaultValue) + { + int newValue; + if (confignode.HasValue(fieldname) && int.TryParse(confignode.GetValue(fieldname), out newValue)) + { + return newValue; + } + return defaultValue; + } + + public static uint GetNodeValue(ConfigNode confignode, string fieldname, uint defaultValue) + { + uint newValue; + if (confignode.HasValue(fieldname) && uint.TryParse(confignode.GetValue(fieldname), out newValue)) + { + return newValue; + } + return defaultValue; + } + + public static double GetNodeValue(ConfigNode confignode, string fieldname, double defaultValue) + { + double newValue; + if (confignode.HasValue(fieldname) && double.TryParse(confignode.GetValue(fieldname), out newValue)) + { + return newValue; + } + return defaultValue; + } + + public static string GetNodeValue(ConfigNode confignode, string fieldname, string defaultValue) + { + if (confignode.HasValue(fieldname)) + { + return confignode.GetValue(fieldname); + } + return defaultValue; + } + + public static Guid GetNodeValue(ConfigNode confignode, string fieldname) + { + if (confignode.HasValue(fieldname)) + { + confignode.GetValue(fieldname); + return new Guid(fieldname); + } + return Guid.Empty; + } + + public static T GetNodeValue(ConfigNode confignode, string fieldname, T defaultValue) where T : IComparable, IFormattable, IConvertible + { + if (confignode.HasValue(fieldname)) + { + string stringValue = confignode.GetValue(fieldname); + if (Enum.IsDefined(typeof(T), stringValue)) + { + return (T)Enum.Parse(typeof(T), stringValue); + } + } + return defaultValue; + } + } +} \ No newline at end of file diff --git a/Source/KerbalPortraits.cs b/Source/KerbalPortraits.cs new file mode 100644 index 0000000..cc44597 --- /dev/null +++ b/Source/KerbalPortraits.cs @@ -0,0 +1,125 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + * + */ +using KSP.UI.Screens.Flight; +using UnityEngine; + + +namespace DeepFreeze +{ + [KSPAddon(KSPAddon.Startup.Flight, false)] + class DFPortraits : MonoBehaviour + { + internal static bool HasPortrait(Kerbal crew, bool checkName = false) + { + if (!checkName) + { + for (int i = 0; i < KerbalPortraitGallery.Instance.Portraits.Count; ++i) + { + if (KerbalPortraitGallery.Instance.Portraits[i].crewMember == crew) + return true; + } + return false; + } + else + { + for (int i = 0; i < KerbalPortraitGallery.Instance.Portraits.Count; ++i) + { + if (KerbalPortraitGallery.Instance.Portraits[i].crewMemberName == crew.crewMemberName) + return true; + } + return false; + } + } + + internal static bool InActiveCrew(Kerbal crew, bool checkName = false) + { + if (!checkName) + { + for (int i = 0; i < KerbalPortraitGallery.Instance.ActiveCrew.Count; ++i) + { + if (KerbalPortraitGallery.Instance.ActiveCrew[i] == crew) + return true; + } + return false; + } + else + { + for (int i = 0; i < KerbalPortraitGallery.Instance.ActiveCrew.Count; ++i) + { + if (KerbalPortraitGallery.Instance.ActiveCrew[i].crewMemberName == crew.crewMemberName) + return true; + } + return false; + } + } + + /// + /// Destroy Portraits for a kerbal and Unregisters them from the KerbalPortraitGallery + /// + /// the Kerbal we want to delete portraits for + internal static void DestroyPortrait(Kerbal kerbal) + { + // set the kerbal InPart to null - this should stop their portrait from re-spawning. + kerbal.InPart = null; + //Set them visible in portrait to false + kerbal.SetVisibleInPortrait(false); + kerbal.state = Kerbal.States.NO_SIGNAL; + //Loop through the ActiveCrew portrait List + for (int i = KerbalPortraitGallery.Instance.ActiveCrew.Count - 1; i >= 0; i--) + { + //If we find an ActiveCrew entry where the crewMemberName is equal to our kerbal's + if (KerbalPortraitGallery.Instance.ActiveCrew[i].crewMemberName == kerbal.crewMemberName) + { + //we Remove them from the list. + KerbalPortraitGallery.Instance.ActiveCrew.RemoveAt(i); + } + } + //Portraits List clean-up. + KerbalPortraitGallery.Instance.DespawnInactivePortraits(); //Despawn any portraits where CrewMember == null + KerbalPortraitGallery.Instance.DespawnPortrait(kerbal); //Despawn our Kerbal's portrait + KerbalPortraitGallery.Instance.UIControlsUpdate(); //Update UI controls + } + + /// + /// Restore the Portrait for a kerbal and register them to the KerbalPortraitGallery + /// + /// the kerbal we want restored + /// the part the kerbal is in + internal static void RestorePortrait(Part part, Kerbal kerbal) + { + //We don't process DEAD, Unowned kerbals - Compatibility with DeepFreeze Mod. + if (kerbal.rosterStatus != ProtoCrewMember.RosterStatus.Dead && + kerbal.protoCrewMember.type != ProtoCrewMember.KerbalType.Unowned) + { + //Set the Kerbals InPart back to their part. + kerbal.InPart = part; + //Set their portrait state to ALIVE and set their portrait back to visible. + kerbal.state = Kerbal.States.ALIVE; + kerbal.SetVisibleInPortrait(true); + //Find an ActiveCrew entry and Portraits entry for our kerbal? + //If they aren't in ActiveCrew and don't have a Portrait them via the kerbal.Start method. + if (!InActiveCrew(kerbal) && !HasPortrait(kerbal)) + { + kerbal.staticOverlayDuration = 1f; + kerbal.randomizeOnStartup = false; + kerbal.Start(); + } + kerbal.state = Kerbal.States.ALIVE; + } + } + } +} diff --git a/Source/PartInfo.cs b/Source/PartInfo.cs new file mode 100644 index 0000000..e4a49eb --- /dev/null +++ b/Source/PartInfo.cs @@ -0,0 +1,184 @@ +/** + * * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + */ + +using System; +using System.Collections.Generic; +using RSTUtils; +using UnityEngine; + +namespace DF +{ + public class PartInfo + { + //This class stores Info about DeepFreezer Parts that have the DeepFreezer partmodule attached. + //VesselID - VesselID of the Vessel this part is a part of. + //PartName - The name of the part + //numSeats - How many seats in the part + //numCrew - How many crew in the part (NOT Frozen) + //crewMembers - List of crewMembers in the part (NOT Frozen) + //crewMemberTraits - Traits of the crewMembers in the part (for display in GUI) + //numFrznCrew - # of frozen crew in the part + //hibernating - true if the part/vessel is unloaded + //hasextDoor - true if the part has an External door and therefore needs TransparentPod treatment, etc. + //hasextPod - True if the part has an external pod and therefore need TransparentPod treatment, etc. + //timeLastElectricity - the time last EC was taken to run the part's Frozen kerbal monitoring + //frznChargeRequired - the amount of EC required per frozen kerbal to run the part's Frozen kerbal monitoring + //timeLastTempCheck - the time last Temperature check was taken on the part + //deathCounter - the EC has run out death counter + //tmpdeathCounter - the Temp is too hot death counter + //outofEC - true if part is out of EC + //TmpStatus - Status of the temperature of the part + //cabinTemp - The part cabin temperature in Kelvin + //lastUpdate - Time this class entry was last updated + // + internal const string ConfigNodeName = "PartInfo"; + + public Guid vesselID; + public string PartName; + public int numSeats; + public int numCrew; + public List crewMembers; + public List crewMemberTraits; + public int numFrznCrew; + public bool hibernating; + public bool hasextDoor; + public bool hasextPod; + public double timeLastElectricity; + public double frznChargeRequired; + public double timeLastTempCheck; + public double deathCounter; + public double tmpdeathCounter; + public bool outofEC; + public FrzrTmpStatus TmpStatus = FrzrTmpStatus.OK; + public bool ECWarning; + public bool TempWarning; + public float cabinTemp; + public double lastUpdate; + + internal PartInfo(Guid vesselid, string PartName, double currentTime) + { + vesselID = vesselid; + this.PartName = PartName; + hibernating = false; + hasextDoor = false; + hasextPod = false; + outofEC = false; + ECWarning = false; + TempWarning = false; + lastUpdate = currentTime; + crewMembers = new List(); + crewMemberTraits = new List(); + } + + internal static PartInfo Load(ConfigNode node) + { + string PartName = "Unknown"; + node.TryGetValue("PartName", ref PartName); + double lastUpdate = 0.0; + node.TryGetValue("lastUpdate", ref lastUpdate); + string tmpvesselID = ""; + node.TryGetValue("vesselID", ref tmpvesselID); + Guid vesselID = Guid.Empty; + try + { + vesselID = new Guid(tmpvesselID); + } + catch (Exception ex) + { + vesselID = Guid.Empty; + Debug.Log("DFInterface - Load of GUID VesselID for known part failed Err: " + ex); + } + PartInfo info = new PartInfo(vesselID, PartName, lastUpdate); + node.TryGetValue("numSeats", ref info.numSeats); + node.TryGetValue("numCrew", ref info.numCrew); + + string CrewString = ""; + node.TryGetValue("crewMembers", ref CrewString); + + string[] CrewStrings = CrewString.Split(','); + if (CrewStrings.Length > 0) + { + for (int i = 0; i < CrewStrings.Length; i++) + { + info.crewMembers.Add(CrewStrings[i]); + } + } + string CrewTraitString = ""; + node.TryGetValue("crewMemberTraits", ref CrewTraitString); + string[] CrewTStrings = CrewTraitString.Split(','); + if (CrewTStrings.Length > 0) + { + for (int i = 0; i < CrewTStrings.Length; i++) + { + info.crewMemberTraits.Add(CrewTStrings[i]); + } + } + node.TryGetValue("numFrznCrew", ref info.numFrznCrew); + node.TryGetValue("hibernating", ref info.hibernating); + node.TryGetValue("hasextDoor", ref info.hasextDoor); + node.TryGetValue("hasextPod", ref info.hasextPod); + node.TryGetValue("timeLastElectricity", ref info.timeLastElectricity); + node.TryGetValue("frznChargeRequired", ref info.frznChargeRequired); + node.TryGetValue("timeLastTempCheck", ref info.timeLastTempCheck); + node.TryGetValue("deathCounter", ref info.deathCounter); + node.TryGetValue("tmpdeathCounter", ref info.tmpdeathCounter); + node.TryGetValue("outofEC", ref info.outofEC); + info.TmpStatus = Utilities.GetNodeValue(node, "TmpStatus", FrzrTmpStatus.OK); + node.TryGetValue("cabinTemp", ref info.cabinTemp); + node.TryGetValue("ECWarning", ref info.ECWarning); + node.TryGetValue("TempWarning", ref info.TempWarning); + + return info; + } + + internal ConfigNode Save(ConfigNode config) + { + ConfigNode node = config.AddNode(ConfigNodeName); + node.AddValue("vesselID", vesselID); + node.AddValue("PartName", PartName); + node.AddValue("numSeats", numSeats); + node.AddValue("numCrew", numCrew); + string crewlst = string.Join(",", crewMembers.ToArray()); + node.AddValue("crewMembers", crewlst); + string crewtrts = string.Join(",", crewMemberTraits.ToArray()); + node.AddValue("crewMemberTraits", crewtrts); + node.AddValue("numFrznCrew", numFrznCrew); + node.AddValue("hibernating", hibernating); + node.AddValue("hasextDoor", hasextDoor); + node.AddValue("hasextPod", hasextPod); + node.AddValue("timeLastElectricity", timeLastElectricity); + node.AddValue("frznChargeRequired", frznChargeRequired); + node.AddValue("timeLastTempCheck", timeLastTempCheck); + node.AddValue("deathCounter", deathCounter); + node.AddValue("tmpdeathCounter", tmpdeathCounter); + node.AddValue("outofEC", outofEC); + node.AddValue("TmpStatus", TmpStatus.ToString()); + node.AddValue("cabinTemp", cabinTemp); + node.AddValue("ECWarning", ECWarning); + node.AddValue("TempWarning", TempWarning); + node.AddValue("lastUpdate", lastUpdate); + return node; + } + + internal void ClearAmounts() + { + numCrew = 0; + numFrznCrew = 0; + timeLastElectricity = 0f; + timeLastTempCheck = 0f; + } + } +} \ No newline at end of file diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs index 70dabf3..4ce8f7f 100644 --- a/Source/Properties/AssemblyInfo.cs +++ b/Source/Properties/AssemblyInfo.cs @@ -1,21 +1,20 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// 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("DeepFreeze")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyDescription("Addon MOD for KerbalSpaceProgram")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DeepFreeze")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2014")] +[assembly: AssemblyCopyright("Copyright © 2015-19")] [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 +// 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)] @@ -25,12 +24,13 @@ // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -// You can specify all the values or you can default the Build and Revision Numbers +// 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")] +[assembly: AssemblyVersion("0.31.0.0")] +[assembly: AssemblyFileVersion("0.31.0.0")] +[assembly: KSPAssembly("DeepFreeze", 0, 31)] \ No newline at end of file diff --git a/Source/RPMScreenDeepFreeze.cs b/Source/RPMScreenDeepFreeze.cs new file mode 100644 index 0000000..acd2293 --- /dev/null +++ b/Source/RPMScreenDeepFreeze.cs @@ -0,0 +1,105 @@ +using System; + +// This is the recommended method to drive a PropMonitor from a foreign plugin, +// because I'm using it myself and now I have to make sure it works. :) +// This module is both a nice gimmick and an example. +// +// This method has the advantage of letting you make use of the variable processing and you don't +// need to copy a page of boilerplate either -- instead, you just need an InternalModule +// with a method that returns a string. That's it. +// +// RasterPropMonitor module can, beyond the usual types of page read from a text file, +// and defined directly in the config file, request a page text from an InternalModule +// living in the same prop as it does. To do this, configure the page like this: +// +// PAGE +// { +// PAGEHANDLER +// { +// name = Name of your module +// method = Method name to be called in your module. +// } +// +// Method name must exist in your module and must be a function that takes two int parameters +// and returns a string. Any other parameters you include in the PAGEHANDLER block +// will be passed to your InternalModule as KSPFields. +// +// RasterPropMonitor will load your module, attach it to the prop it lives in and +// poll this function every time it decides the page needs to be refreshed. You need +// to return a string, that will then be processed just like a page definition text file. +// You will obviously want your own namespace. +namespace DF +{ + // It needs to be an InternalModule. + public class RPMScreenDeepFreeze : InternalModule + { + // These KSPFields will actually be loaded from the PAGEHANDLER block + [KSPField] + public string pageTitle; + + // We can keep our response buffered and only return it upon request. + private string response; + + // We only update the response when the number of lines in the flight log changes. + private int lastCount = -1; + + // This method will be found by RasterPropMonitorGenerator and called to provide a page. + // You must return a string. Environment.Newline is the carriage return, nothing fancy. + public string ShowLog(int screenWidth, int screenHeight) + { + if (FlightLogger.eventLog.Count != lastCount) + { + LogToBuffer(screenWidth, screenHeight); + } + return response; + } + + // I honestly have no clue why InternalModules need to be initialised + // like this, and not with a proper constructor or an OnAwake, but that one always works. + // Even a very simple OnAwake can sometimes get the entire IVA to choke. + public void Start() + { + if (!string.IsNullOrEmpty(pageTitle)) + // Notice that UnMangleConfigText is an extension method defined in JUtil class. + // To your module, it won't be available without hardlinking to RPM, which is what you want to avoid. + // It's nothing you couldn't replace with .Replace("<=", "{").Replace("=>", "}").Replace("$$$", Environment.NewLine); though + pageTitle = pageTitle.Replace("<=", "{").Replace("=>", "}").Replace("$$$", Environment.NewLine); + } + + // You can have an OnUpdate in this module, this particular one doesn't need it. + private void LogToBuffer(int screenWidth, int screenHeight) + { + // I think I coded this one backwards somehow, but eh, it's a gimmick. + int activeScreenHeight = screenHeight; + if (!string.IsNullOrEmpty(pageTitle)) + { + activeScreenHeight--; + } + lastCount = FlightLogger.eventLog.Count; + if (lastCount > 0) + { + string fullLog = Utilities.WordWrap(string.Join(Environment.NewLine, FlightLogger.eventLog.ToArray()), screenWidth); + var tempBuffer = fullLog.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + var screenBuffer = new string[activeScreenHeight]; + if (tempBuffer.Length <= activeScreenHeight) + { + screenBuffer = tempBuffer; + } + else + { + for (int i = 0; i < screenBuffer.Length; i++) + { + screenBuffer[i] = tempBuffer[tempBuffer.Length - activeScreenHeight + i]; + } + } + response = string.Join(Environment.NewLine, screenBuffer); + } + else + response = "No records in log."; + if (!string.IsNullOrEmpty(pageTitle)) + { + response = pageTitle + Environment.NewLine + response; + } + } + } +} \ No newline at end of file diff --git a/Source/SettingsParms.cs b/Source/SettingsParms.cs new file mode 100644 index 0000000..fb94562 --- /dev/null +++ b/Source/SettingsParms.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using UnityEngine; +using KSP.Localization; + +namespace DF +{ + public class DeepFreeze_SettingsParms : GameParameters.CustomParameterNode + + { + public override string Title { get { return Localizer.Format("#autoLOC_DF_00144"); } } //#autoLOC_DF_00144 = DeepFreeze Options + public override GameParameters.GameMode GameMode { get { return GameParameters.GameMode.ANY; } } + public override bool HasPresets { get { return true; } } + public override string Section { get { return "DeepFreeze"; } } + public override string DisplaySection { get { return Localizer.Format("#autoLOC_DF_00003"); } } //#autoLOC_DF_00003 = DeepFreeze + public override int SectionOrder { get { return 1; } } + + + [GameParameters.CustomParameterUI("#autoLOC_DF_00145", autoPersistance = true, toolTip = "#autoLOC_DF_00146")] //#autoLOC_DF_00145 = ElectricCharge Required to run Freezers #autoLOC_DF_00146 = If on, EC is required to run freezers + public bool ECreqdForFreezer = false; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00201", autoPersistance = true, toolTip = "#autoLOC_DF_00202")] //#autoLOC_DF_00201 = Unloaded Vessel Processing //#autoLOC_DF_00202 = If enabled DeepFreeze will process resources on unloaded vessels. If disabled, it won't and play the catchup and estimation game. + public bool backgroundresources = true; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00147", autoPersistance = true, toolTip = "#autoLOC_DF_00148")] //#autoLOC_DF_00147 = Fatal EC/Heat Option #autoLOC_DF_00148 = If on Kerbals will die if EC runs out or it gets too hot + public bool fatalOption = false; + + [GameParameters.CustomIntParameterUI("#autoLOC_DF_00149", minValue = 60, maxValue = 10000, stepSize = 60, autoPersistance = true, toolTip = "#autoLOC_DF_00150")] //#autoLOC_DF_00149 = Non Fatal Comatose Time(in secs) #autoLOC_DF_00150 = The time in seconds a kerbal is comatose\n if fatal EC / Heat option is off + public int comatoseTime = 300; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00151", autoPersistance = true, toolTip = "#autoLOC_DF_00152")] //#autoLOC_DF_00151 = AutoRecover Frozen Kerbals at KSC #autoLOC_DF_00152 = If on, will AutoRecover Frozen Kerbals at the KSC\n and deduct the Cost from your funds + public bool AutoRecoverFznKerbals = false; + + [GameParameters.CustomFloatParameterUI("#autoLOC_DF_00153", toolTip = "#autoLOC_DF_00154", minValue = 0, maxValue = 500000, gameMode = GameParameters.GameMode.CAREER)] //#autoLOC_DF_00153 = Cost to Thaw a Kerbal at KSC #autoLOC_DF_00154 = Amt of currency Reqd to Freeze a Kerbal from the KSC + public float KSCcostToThawKerbal = 10000f; + + [GameParameters.CustomIntParameterUI("#autoLOC_DF_00155", autoPersistance = true, minValue = 0, maxValue = 10000, stepSize = 10, toolTip = "#autoLOC_DF_00156")] //#autoLOC_DF_00155 = EC Reqd to Freeze/Thaw a Kerbal #autoLOC_DF_00156 = Amt of ElecCharge Reqd to Freeze/Thaw a Kerbal. + public int ECReqdToFreezeThaw = 3000; + + [GameParameters.CustomIntParameterUI("#autoLOC_DF_00157", autoPersistance = true, minValue = 0, maxValue = 50, toolTip = "#autoLOC_DF_00158")] //#autoLOC_DF_00157 = Glykerol Reqd to Freeze a Kerbal #autoLOC_DF_00158 = Amt of Glykerol used to Freeze a Kerbal,\nOverrides Part values. + public int GlykerolReqdToFreeze = 5; + + public override void SetDifficultyPreset(GameParameters.Preset preset) + { + Debug.Log("Setting difficulty preset"); + switch (preset) + { + case GameParameters.Preset.Easy: + this.ECreqdForFreezer = false; + this.backgroundresources = false; + this.AutoRecoverFznKerbals = true; + this.KSCcostToThawKerbal = 5000f; + this.ECReqdToFreezeThaw = 1000; + this.GlykerolReqdToFreeze = 5; + break; + case GameParameters.Preset.Normal: + this.ECreqdForFreezer = false; + this.backgroundresources = false; + this.AutoRecoverFznKerbals = true; + this.KSCcostToThawKerbal = 10000f; + this.ECReqdToFreezeThaw = 2000; + this.GlykerolReqdToFreeze = 5; + break; + case GameParameters.Preset.Moderate: + this.ECreqdForFreezer = true; + this.backgroundresources = true; + this.AutoRecoverFznKerbals = false; + this.KSCcostToThawKerbal = 20000f; + this.ECReqdToFreezeThaw = 3000; + this.GlykerolReqdToFreeze = 10; + break; + case GameParameters.Preset.Hard: + this.ECreqdForFreezer = true; + this.backgroundresources = true; + this.AutoRecoverFznKerbals = false; + this.KSCcostToThawKerbal = 30000f; + this.ECReqdToFreezeThaw = 4000; + this.GlykerolReqdToFreeze = 15; + break; + } + } + + public override bool Enabled(MemberInfo member, GameParameters parameters) + { + if (HighLogic.fetch != null) + { + if (HighLogic.LoadedSceneIsFlight) + { + return false; + } + } + + return true; + } + + public override bool Interactible(MemberInfo member, GameParameters parameters) + { + if (HighLogic.fetch != null) + { + if (HighLogic.LoadedSceneIsFlight) + { + return false; + } + } + if (member.Name == "backgroundresources") + { + return DFInstalledMods.IsBGRInstalled; + } + + if (member.Name == "fatalOption") + { + return parameters.CustomParams().ECreqdForFreezer; + } + if (member.Name == "comatoseTime") + { + return (parameters.CustomParams().ECreqdForFreezer && + !parameters.CustomParams().fatalOption); + } + if (member.Name == "KSCcostToThawKerbal") + { + return parameters.CustomParams().AutoRecoverFznKerbals; + } + + return true; + } + } + + public class DeepFreeze_SettingsParms_Sec2 : GameParameters.CustomParameterNode + + { + public override string Title { get { return Localizer.Format("#autoLOC_DF_00159"); } } //#autoLOC_DF_00159 = DeepFreeze Temperatures + public override GameParameters.GameMode GameMode { get { return GameParameters.GameMode.ANY; } } + public override bool HasPresets { get { return true; } } + public override string Section { get { return "DeepFreeze"; } } + public override string DisplaySection { get { return Localizer.Format("#autoLOC_DF_00003"); } } //#autoLOC_DF_00003 = DeepFreeze + public override int SectionOrder { get { return 2; } } + + [GameParameters.CustomStringParameterUI("Test String UI", lines = 3, title = "", toolTip = "#autoLOC_DF_00160")] //#autoLOC_DF_00160 = Get your calculator out. + public string CBstring = "#autoLOC_DF_00161"; //#autoLOC_DF_00161 = Temps are in (K)elvin. (K) = (C)elcius + 273.15. (K) = ((F)arenheit + 459.67) × 5/9. Get your calculator out + + [GameParameters.CustomParameterUI("#autoLOC_DF_00162", autoPersistance = true, toolTip = "#autoLOC_DF_00163")] //#autoLOC_DF_00162 = Regulated Temperatures Required #autoLOC_DF_00163 = If on, Regulated Temps apply to freeze\nand keep Kerbals Frozen. + public bool RegTempReqd = false; + + [GameParameters.CustomFloatParameterUI("#autoLOC_DF_00164", autoPersistance = true, minValue = 0, maxValue = 400, toolTip = "#autoLOC_DF_00165")] //#autoLOC_DF_00164 = Min. Temp. for Freezer to Freeze(K) #autoLOC_DF_00165 = The minimum temperature (in Kelvin) for a Freezer\nto be able to Freeze a Kerbal. + public float RegTempFreeze = 300f; + + [GameParameters.CustomFloatParameterUI("#autoLOC_DF_00166", autoPersistance = true, minValue = 0, maxValue = 800, toolTip = "#autoLOC_DF_00167")] //#autoLOC_DF_00166 = Max. Temp. to keep Kerbals Frozen(K) #autoLOC_DF_00167 = The maximum temperature (in Kelvin) for a Freezer\nto keep Kerbals frozen. + public float RegTempMonitor = 400f; + + [GameParameters.CustomFloatParameterUI("#autoLOC_DF_00168", autoPersistance = true, minValue = 10, maxValue = 1000, toolTip = "#autoLOC_DF_00169")] //#autoLOC_DF_00168 = Heat generated per kerbal (kW/min) #autoLOC_DF_00169 = Amount of thermal heat (kW) generated\nby equipment for each frozen kerbal per minute. + public float heatamtMonitoringFrznKerbals = 100f; + + [GameParameters.CustomFloatParameterUI("#autoLOC_DF_00170", autoPersistance = true, minValue = 10, maxValue = 3000, toolTip = "#autoLOC_DF_00171")] //#autoLOC_DF_00170 = Heat generated freezer process(kW) #autoLOC_DF_00171 = Amount of thermal heat (kW) generated\nwith each thaw/freeze process. + public float heatamtThawFreezeKerbal = 1000f; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00172", autoPersistance = true, toolTip = "#autoLOC_DF_00173")] //#autoLOC_DF_00172 = Show Part Temperatures in Kelvin #autoLOC_DF_00173 = If on Part right click will show temp in Kelvin,\nif Off will show in Celcius. + public bool TempinKelvin = false; + + public override void SetDifficultyPreset(GameParameters.Preset preset) + { + Debug.Log("Setting difficulty preset"); + switch (preset) + { + case GameParameters.Preset.Easy: + this.RegTempReqd = false; + break; + case GameParameters.Preset.Normal: + this.RegTempReqd = false; + break; + case GameParameters.Preset.Moderate: + this.RegTempReqd = true; + break; + case GameParameters.Preset.Hard: + this.RegTempReqd = true; + break; + } + } + + public override bool Interactible(MemberInfo member, GameParameters parameters) + { + if (HighLogic.fetch != null) + { + if (HighLogic.LoadedSceneIsFlight) + { + if (member.Name != "TempinKelvin") + return false; + } + } + + if (member.Name == "RegTempFreeze" || member.Name == "RegTempMonitor" || member.Name == "heatamtMonitoringFrznKerbals" || member.Name == "heatamtThawFreezeKerbal") + { + return parameters.CustomParams().RegTempReqd; + } + + return true; + } + } + + public class DeepFreeze_SettingsParms_Sec3 : GameParameters.CustomParameterNode + + { + public override string Title { get { return Localizer.Format("#autoLOC_DF_00174"); } } //#autoLOC_DF_00174 = DeepFreeze Misc. + public override GameParameters.GameMode GameMode { get { return GameParameters.GameMode.ANY; } } + public override bool HasPresets { get { return false; } } + public override string Section { get { return "DeepFreeze"; } } + public override string DisplaySection { get { return Localizer.Format("#autoLOC_DF_00003"); } } //#autoLOC_DF_00003 = DeepFreeze + public override int SectionOrder { get { return 3; } } + + [GameParameters.CustomParameterUI("#autoLOC_DF_00175", autoPersistance = true, toolTip = "#autoLOC_DF_00176")] //#autoLOC_DF_00175 = Freezer Strip Lights On #autoLOC_DF_00176 = Turn off if you do not want the internal\nfreezer strip lights to function. + public bool StripLightsActive = true; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00203", autoPersistance = true, toolTip = "#autoLOC_DF_00204")] //#autoLOC_DF_00203 = Beep Sounds On. #autoLOC_DF_00204 = If enabled Beep sounds are heard inside freezer parts with frozen kerbals. + public bool BeepSoundsActive = true; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00205", autoPersistance = true, toolTip = "#autoLOC_DF_00206")] //#autoLOC_DF_00205 = Other Sounds On. #autoLOC_DF_00206 = If enabled all other DeepFreeze sounds are heard. + public bool OtherSoundsActive = true; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00177", autoPersistance = true, toolTip = "#autoLOC_DF_00178")] //#autoLOC_DF_00177 = ToolTips On #autoLOC_DF_00178 = Turn the Tooltips on and off. + public bool ToolTips = true; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00179", autoPersistance = true, toolTip = "#autoLOC_DF_00180")] //#autoLOC_DF_00179 = Editor Filter #autoLOC_DF_00180 = Turn the DeepFreeze Editor filter Category on and off. + public bool EditorFilter = true; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00181", toolTip = "#autoLOC_DF_00182")] //#autoLOC_DF_00181 = Use Stock App Launcher Icon #autoLOC_DF_00182 = If on, the Stock Application launcher will be used,\nif off will use Blizzy Toolbar if installed. + public bool UseAppLToolbar = true; + + [GameParameters.CustomParameterUI("#autoLOC_DF_00183", toolTip = "#autoLOC_DF_00184")] //#autoLOC_DF_00183 = Extra Debug Logging #autoLOC_DF_00184 = Turn this On to capture lots of extra information\ninto the KSP log for reporting a problem. + public bool DebugLogging = false; + + public override bool Interactible(MemberInfo member, GameParameters parameters) + { + if (member.Name == "UseAppLToolbar") + { + if (RSTUtils.ToolbarManager.ToolbarAvailable) + return true; + return false; + } + + return true; + } + } +} diff --git a/Source/Textures.cs b/Source/Textures.cs new file mode 100644 index 0000000..3401611 --- /dev/null +++ b/Source/Textures.cs @@ -0,0 +1,229 @@ +// The following Class is derived from Kerbal Alarm Clock mod. Which is licensed under: +// The MIT License(MIT) Copyright(c) 2014, David Tregoning +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using UnityEngine; +using RSTUtils; + +namespace DF +{ + [KSPAddon(KSPAddon.Startup.MainMenu, false)] + public class LoadGlobals : MonoBehaviour + { + public static LoadGlobals Instance; + //Awake Event - when the DLL is loaded + public void Awake() + { + if (Instance != null) + return; + Instance = this; + Textures.LoadIconAssets(); + DontDestroyOnLoad(this); + //Utilities.Log("DeepFreeze LoadGlobals Awake Complete"); + } + + public void Start() + { + //GameEvents.onGameSceneSwitchRequested.Add(onGameSceneSwitchRequested); + DFGameEvents.onKerbalFrozen = new EventData("onKerbalFrozen"); + DFGameEvents.onKerbalThaw = new EventData("onKerbalThaw"); + DFGameEvents.onKerbalFreezing = new EventData("onKerbalFreezing"); + DFGameEvents.onKerbalThawing = new EventData("onKerbalThawing"); + DFGameEvents.onKerbalFreezeAbort = new EventData("onKerbalFreezeAbort"); + DFGameEvents.onKerbalThawAbort = new EventData("onKerbalThawAbort"); + DFGameEvents.onKerbalSetComatose = new EventData("onKerbalSetComatose"); + DFGameEvents.onKerbalUnSetComatose = new EventData("onKerbalUnSetComatose"); + DFGameEvents.onFrozenKerbalDied = new EventData("onFrozenKerbalDied"); + } + + public void OnDestroy() + { + //GameEvents.onGameSceneSwitchRequested.Remove(onGameSceneSwitchRequested); + } + } + + internal static class Textures + { + + internal static Texture2D TooltipBox = new Texture2D(10, 10, TextureFormat.ARGB32, false); + internal static Texture2D BtnRedCross = new Texture2D(16, 16, TextureFormat.ARGB32, false); + internal static Texture2D BtnResize = new Texture2D(16, 16, TextureFormat.ARGB32, false); + internal static Texture2D DeepFreeze_Editor = new Texture2D(32, 32, TextureFormat.ARGB32, false); + + internal static String PathIconsPath = System.IO.Path.Combine(DeepFreeze._AssemblyFolder.Substring(0, DeepFreeze._AssemblyFolder.IndexOf("/DeepFreeze/") + 12), "Icons").Replace("\\", "/"); + internal static String PathToolbarIconsPath = PathIconsPath.Substring(PathIconsPath.ToLower().IndexOf("/gamedata/") + 10); + + + internal static void LoadIconAssets() + { + try + { + //Utilities.Log("DeepFreeze AssemblyFolder = " + DeepFreeze._AssemblyFolder); + //Utilities.Log("PathIconsPath = " + PathIconsPath); + //Utilities.Log("PathToolbarIconsPath = " + PathToolbarIconsPath); + LoadImageFromFile(ref TooltipBox, "DFToolTipBox.png", PathIconsPath); + LoadImageFromFile(ref BtnRedCross, "DFbtnRedCross.png", PathIconsPath); + LoadImageFromFile(ref BtnResize, "DFbtnResize.png", PathIconsPath); + LoadImageFromFile(ref DeepFreeze_Editor, "DeepFreezeEditor.png", PathIconsPath); + } + catch (Exception) + { + RSTUtils.Utilities.Log("DeepFreeze Failed to Load Textures - are you missing a file?"); + } + } + + public static Boolean LoadImageFromFile(ref Texture2D tex, String fileName, String folderPath = "") + { + Boolean blnReturn = false; + try + { + if (folderPath == "") folderPath = PathIconsPath; + + //File Exists check + if (System.IO.File.Exists(String.Format("{0}/{1}", folderPath, fileName))) + { + try + { + tex.LoadImage(System.IO.File.ReadAllBytes(String.Format("{0}/{1}", folderPath, fileName))); + blnReturn = true; + } + catch (Exception ex) + { + RSTUtils.Utilities.Log("TST Failed to load the texture:" + folderPath + "(" + fileName + ")"); + RSTUtils.Utilities.Log(ex.Message); + } + } + else + { + RSTUtils.Utilities.Log("Cannot find texture to load:" + folderPath + "(" + fileName + ")"); + } + + + } + catch (Exception ex) + { + RSTUtils.Utilities.Log("Failed to load (are you missing a file):" + folderPath + "(" + fileName + ")"); + RSTUtils.Utilities.Log(ex.Message); + } + return blnReturn; + } + + internal static GUIStyle ResizeStyle, ClosebtnStyle; + internal static GUIStyle statusStyle, frozenStyle, comaStyle, sectionTitleLeftStyle, sectionTitleCenterStyle, resizeStyle, StatusOKStyle, + StatusWarnStyle, StatusRedStyle, StatusGrayStyle, ButtonStyle; + + + internal static bool StylesSet = false; + + internal static void SetupStyles() + { + GUI.skin = HighLogic.Skin; + + //Init styles + + Utilities._TooltipStyle = new GUIStyle(GUI.skin.label) + { + fontSize = 12, + fontStyle = FontStyle.Normal, + stretchHeight = true, + wordWrap = true, + border = new RectOffset(3, 3, 3, 3), + padding = new RectOffset(4, 4, 6, 4), + alignment = TextAnchor.MiddleCenter + }; + Utilities._TooltipStyle.normal.background = Textures.TooltipBox; + Utilities._TooltipStyle.normal.textColor = new Color32(207, 207, 207, 255); + Utilities._TooltipStyle.hover.textColor = Color.blue; + + ClosebtnStyle = new GUIStyle(GUI.skin.button) + { + alignment = TextAnchor.MiddleCenter, + fixedWidth = 20, + fixedHeight = 20, + fontSize = 14, + fontStyle = FontStyle.Normal + }; + ClosebtnStyle.active.background = GUI.skin.toggle.onNormal.background; + ClosebtnStyle.onActive.background = ClosebtnStyle.active.background; + ClosebtnStyle.padding = Utilities.SetRectOffset(ClosebtnStyle.padding, 3); + + ResizeStyle = new GUIStyle(GUI.skin.button) + { + alignment = TextAnchor.MiddleCenter, + fixedWidth = 20, + fixedHeight = 20, + fontSize = 14, + fontStyle = FontStyle.Normal + }; + ResizeStyle.onActive.background = ClosebtnStyle.active.background; + ResizeStyle.padding = Utilities.SetRectOffset(ClosebtnStyle.padding, 3); + + //Init styles + sectionTitleLeftStyle = new GUIStyle(GUI.skin.label); + sectionTitleLeftStyle.alignment = TextAnchor.MiddleLeft; + sectionTitleLeftStyle.stretchWidth = true; + sectionTitleLeftStyle.normal.textColor = Color.cyan; + sectionTitleLeftStyle.fontStyle = FontStyle.Bold; + + sectionTitleCenterStyle = new GUIStyle(GUI.skin.label); + sectionTitleCenterStyle.alignment = TextAnchor.MiddleCenter; + sectionTitleCenterStyle.stretchWidth = true; + sectionTitleCenterStyle.fontStyle = FontStyle.Bold; + + statusStyle = new GUIStyle(GUI.skin.label); + statusStyle.alignment = TextAnchor.MiddleLeft; + statusStyle.stretchWidth = true; + statusStyle.normal.textColor = Color.white; + + frozenStyle = new GUIStyle(GUI.skin.label); + frozenStyle.alignment = TextAnchor.MiddleLeft; + frozenStyle.stretchWidth = true; + frozenStyle.normal.textColor = Color.cyan; + + comaStyle = new GUIStyle(GUI.skin.label); + comaStyle.alignment = TextAnchor.MiddleLeft; + comaStyle.stretchWidth = true; + comaStyle.normal.textColor = Color.gray; + + StatusOKStyle = new GUIStyle(GUI.skin.label); + StatusOKStyle.alignment = TextAnchor.MiddleLeft; + StatusOKStyle.stretchWidth = true; + StatusOKStyle.normal.textColor = Color.green; + + StatusWarnStyle = new GUIStyle(GUI.skin.label); + StatusWarnStyle.alignment = TextAnchor.MiddleLeft; + StatusWarnStyle.stretchWidth = true; + StatusWarnStyle.normal.textColor = Color.yellow; + + StatusRedStyle = new GUIStyle(GUI.skin.label); + StatusRedStyle.alignment = TextAnchor.MiddleLeft; + StatusRedStyle.stretchWidth = true; + StatusRedStyle.normal.textColor = Color.red; + + StatusGrayStyle = new GUIStyle(GUI.skin.label); + StatusGrayStyle.alignment = TextAnchor.MiddleLeft; + StatusGrayStyle.stretchWidth = true; + StatusGrayStyle.normal.textColor = Color.gray; + + resizeStyle = new GUIStyle(GUI.skin.button); + resizeStyle.alignment = TextAnchor.MiddleCenter; + resizeStyle.padding = new RectOffset(1, 1, 1, 1); + + ButtonStyle = new GUIStyle(GUI.skin.toggle); + ButtonStyle.margin.top = 0; + ButtonStyle.margin.bottom = 0; + ButtonStyle.padding.top = 0; + ButtonStyle.padding.bottom = 0; + + StylesSet = true; + } + } +} \ No newline at end of file diff --git a/Source/VesselInfo.cs b/Source/VesselInfo.cs new file mode 100644 index 0000000..e32adac --- /dev/null +++ b/Source/VesselInfo.cs @@ -0,0 +1,113 @@ +/** + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license. See + * for full details. + */ + +using RSTUtils; + +namespace DF +{ + public class VesselInfo + { + //This class stores Info about vessels that have the DeepFreezer parts attached. + //VesselName - Name of the vessel + //vesselType - The vessel type. + //numCrew - Number of crew on-board (does not include FROZEN crew) + //numSeats - Number of seats in total on vessel + //numOccupiedParts - Number of parts that are currently occupied (does include FROZEN crew) + //numFrznCrew - Number of frozen crew on-board + //hibernating - True if vessel is unloaded + //hasextDoor - True if somewhere on the vessel is a DeepFreezer part with an external door + //hasextPod - True if somewhere on the vessel is a DeepFreezer part with an external pod + //lastUpdate - Time this class entry was last updated + //storedEC - How much ElectricCharge the vessel has + //predictedECOut - Predicted time in seconds ElectricCharge will run out (by just running the freezers) + public const string ConfigNodeName = "VesselInfo"; + + public string vesselName; + public VesselType vesselType = VesselType.Unknown; + public int numCrew; + public int numSeats; + public int numOccupiedParts; + public int numFrznCrew; + public bool hibernating; + public bool hasextDoor; + public bool hasextPod; + public double lastUpdate; + public double storedEC; + public double predictedECOut; + + internal VesselInfo(string vesselName, double currentTime) + { + this.vesselName = vesselName; + hibernating = false; + hasextDoor = false; + hasextPod = false; + lastUpdate = currentTime; + } + + internal static VesselInfo Load(ConfigNode node) + { + string vesselName = "Unknown"; + node.TryGetValue("vesselName", ref vesselName); + double lastUpdate = 0f; + node.TryGetValue("lastUpdate", ref lastUpdate); + //string vesselName = Utilities.GetNodeValue(node, "vesselName", "Unknown"); + //double lastUpdate = Utilities.GetNodeValue(node, "lastUpdate", 0.0); + + VesselInfo info = new VesselInfo(vesselName, lastUpdate); + node.TryGetValue("numSeats", ref info.numSeats); + node.TryGetValue("numCrew", ref info.numCrew); + node.TryGetValue("numOccupiedParts", ref info.numOccupiedParts); + node.TryGetValue("numFrznCrew", ref info.numFrznCrew); + node.TryGetValue("hibernating", ref info.hibernating); + node.TryGetValue("hasextDoor", ref info.hasextDoor); + node.TryGetValue("hasextPod", ref info.hasextPod); + node.TryGetValue("storedEC", ref info.storedEC); + node.TryGetValue("predictedECOut", ref info.predictedECOut); + + info.vesselType = Utilities.GetNodeValue(node, "vesselType", VesselType.Unknown); + + return info; + } + + internal ConfigNode Save(ConfigNode config) + { + ConfigNode node = config.AddNode(ConfigNodeName); + node.AddValue("vesselName", vesselName); + node.AddValue("vesselType", vesselType.ToString()); + node.AddValue("numSeats", numSeats); + node.AddValue("numCrew", numCrew); + node.AddValue("numOccupiedParts", numOccupiedParts); + node.AddValue("numFrznCrew", numFrznCrew); + node.AddValue("hibernating", hibernating); + node.AddValue("hasextDoor", hasextDoor); + node.AddValue("hasextPod", hasextPod); + node.AddValue("lastUpdate", lastUpdate); + node.AddValue("storedEC", storedEC); + node.AddValue("predictedECOut", predictedECOut); + return node; + } + + internal void ClearAmounts() + { + numCrew = 0; + numOccupiedParts = 0; + numFrznCrew = 0; + numSeats = 0; + storedEC = 0f; + predictedECOut = 0f; + } + } +} \ No newline at end of file diff --git a/Source/testsettings.DotSettings b/Source/testsettings.DotSettings new file mode 100644 index 0000000..640e19f --- /dev/null +++ b/Source/testsettings.DotSettings @@ -0,0 +1,4 @@ + + UseExplicitType + UseExplicitType + UseExplicitType \ No newline at end of file