public TechLevel(TechLevel t) { atmosphereCurve = t.atmosphereCurve; velocityCurve = t.velocityCurve; TWR = t.TWR; thrustMultiplier = t.thrustMultiplier; massMultiplier = t.massMultiplier; gimbalRange = t.gimbalRange; techRequired = t.techRequired; minThrottleMultiplier = t.minThrottleMultiplier; costMult = t.costMult; LoadGlobals(); }
public override string GetInfo() { if (!compatible) return ""; if (configs.Count < 2) return TLTInfo(); string info = TLTInfo() + "\nAlternate configurations:\n"; //Unused as yet /*TechLevel moduleTLInfo = new TechLevel(); if (techNodes != null) moduleTLInfo.Load(techNodes, techLevel); else moduleTLInfo = null;*/ foreach (ConfigNode config in configs) { TechLevel cTL = new TechLevel(); if (!cTL.Load(config, techNodes, engineType, techLevel)) cTL = null; if(!config.GetValue ("name").Equals (configuration)) { info += " " + config.GetValue ("name") + "\n"; if(config.HasValue (thrustRating)) info += " (" + (scale * ThrustTL(config.GetValue (thrustRating), config)).ToString("0.00") + " Thrust"; else info += " (Unknown Thrust"; float cst; if(config.HasValue("cost") && float.TryParse(config.GetValue("cost"), out cst)) info += " (" + (scale*cst).ToString("N0") + " extra cost)"; // FIXME should get cost from TL, but this should be safe // because it will always be the cost for the original TL, and thus unmodified. FloatCurve isp = new FloatCurve(); if(config.HasNode ("atmosphereCurve")) { isp.Load (config.GetNode ("atmosphereCurve")); info += ", " + isp.Evaluate (isp.maxTime).ToString() + "-" + isp.Evaluate (isp.minTime).ToString() + "Isp"; } else if (config.HasValue("IspSL") && config.HasValue("IspV")) { float ispSL = 1.0f, ispV = 1.0f; float.TryParse(config.GetValue("IspSL"), out ispSL); float.TryParse(config.GetValue("IspV"), out ispV); if (cTL != null) { ispSL *= ispSLMult * cTL.AtmosphereCurve.Evaluate(1); ispV *= ispVMult * cTL.AtmosphereCurve.Evaluate(0); info += ", " + ispSL.ToString("0") + "-" + ispV.ToString("0") + "Isp"; } } float gimbalR = -1f; if (config.HasValue("gimbalRange")) gimbalR = float.Parse(config.GetValue("gimbalRange")); // Don't do per-TL checks here, they're misleading. /*else if (!gimbalTransform.Equals("") || useGimbalAnyway) { if (cTL != null) gimbalR = cTL.GimbalRange; }*/ if (gimbalR != -1f) info += ", Gimbal " + gimbalR.ToString("N1"); if (config.HasValue("ullage")) info += ", " + (config.GetValue("ullage").ToLower() == "true" ? "ullage" : "no ullage"); if (config.HasValue("pressureFed") && config.GetValue("pressureFed").ToLower() == "true") info += ", pfed"; if (config.HasValue("ignitions")) { int ignitions; if (int.TryParse(config.GetValue("ignitions"), out ignitions)) { if (ignitions > 0) info += ", " + ignitions + " ignition" + (ignitions > 1 ? "s" : ""); else info += ", unl. ignitions"; } } info += ")\n"; } } return info; }
public virtual void DoConfig(ConfigNode cfg) { configMaxThrust = configMinThrust = configHeat = -1f; // Get thrusts if (config.HasValue(thrustRating)) { float thr; if (float.TryParse(config.GetValue(thrustRating), out thr)) configMaxThrust = scale * thr; } if (config.HasValue("minThrust")) { float thr; if (float.TryParse(config.GetValue("minThrust"), out thr)) configMinThrust = scale * thr; } // Get, multiply heat if (cfg.HasValue("heatProduction")) { float heat; if(float.TryParse(cfg.GetValue("heatProduction"), out heat)) configHeat = (float)Math.Round(heat * RFSettings.Instance.heatMultiplier, 0); } // load throttle (for later) configThrottle = throttle; if (cfg.HasValue("throttle")) float.TryParse(cfg.GetValue("throttle"), out configThrottle); else if (configMinThrust >= 0f && configMaxThrust >= 0f) configThrottle = configMinThrust / configMaxThrust; float TLMassMult = 1.0f; float gimbal = -1f; if (cfg.HasValue("gimbalRange")) gimbal = float.Parse(cfg.GetValue("gimbalRange")); float cost = 0f; if (cfg.HasValue("cost")) cost = scale * float.Parse(cfg.GetValue("cost")); if (techLevel != -1) { // load techlevels TechLevel cTL = new TechLevel(); cTL.Load(cfg, techNodes, engineType, techLevel); TechLevel oTL = new TechLevel(); oTL.Load(cfg, techNodes, engineType, origTechLevel); // set atmosphereCurve if (cfg.HasValue("IspSL") && cfg.HasValue("IspV")) { cfg.RemoveNode("atmosphereCurve"); ConfigNode curve = new ConfigNode("atmosphereCurve"); // get the multipliers float ispSL = 1f, ispV = 1f; float.TryParse(cfg.GetValue("IspSL"), out ispSL); float.TryParse(cfg.GetValue("IspV"), out ispV); // Mod the curve by the multipliers FloatCurve newAtmoCurve = new FloatCurve(); newAtmoCurve = Utilities.Mod(cTL.AtmosphereCurve, ispSL, ispV); newAtmoCurve.Save(curve); cfg.AddNode(curve); } // set heatProduction if (configHeat > 0) { configHeat = MassTL(configHeat); } // set thrust and throttle if (configMaxThrust >= 0) { configMaxThrust = ThrustTL(configMaxThrust); if (configMinThrust >= 0) { configMinThrust = ThrustTL(configMinThrust); } else if (thrustRating.Equals("thrusterPower")) { configMinThrust = configMaxThrust * 0.5f; } else { configMinThrust = configMaxThrust; if (configThrottle > 1.0f) { if (techLevel >= configThrottle) configThrottle = 1.0f; else configThrottle = -1.0f; } if (configThrottle >= 0.0f) { configThrottle = (float)((double)configThrottle * cTL.Throttle()); configMinThrust *= configThrottle; } } configThrottle = configMinThrust / configMaxThrust; if (origMass > 0) TLMassMult = MassTL(1.0f); } // Don't want to change gimbals on TL-enabled engines willy-nilly // So we don't unless either a transform is specified, or we override. // We assume if it was specified in the CONFIG that we should use it anyway. if (gimbal < 0 && (!gimbalTransform.Equals("") || useGimbalAnyway)) gimbal = cTL.GimbalRange; if (gimbal >= 0) { // allow local override of gimbal mult if (cfg.HasValue("gimbalMult")) gimbal *= float.Parse(cfg.GetValue("gimbalMult")); } // Cost (multiplier will be 1.0 if unspecified) cost = scale * CostTL(cost, cfg); } else { if (cfg.HasValue(thrustRating) && configThrottle > 0f && !cfg.HasValue("minThrust")) { configMinThrust = configThrottle * configMaxThrust; } } // Now update the cfg from what we did. // thrust updates if(configMaxThrust >= 0f) cfg.SetValue(thrustRating, configMaxThrust.ToString("0.0000")); if(configMinThrust >= 0f) cfg.SetValue("minThrust", configMinThrust.ToString("0.0000")); // will be ignored by RCS, so what. // heat update if(configHeat >= 0f) cfg.SetValue("heatProduction", configHeat.ToString("0")); // mass change if (origMass > 0) { float ftmp; configMassMult = scale; if (cfg.HasValue("massMult")) if (float.TryParse(cfg.GetValue("massMult"), out ftmp)) configMassMult *= ftmp; part.mass = origMass * configMassMult * RFSettings.Instance.EngineMassMultiplier * TLMassMult; massDelta = 0; if ((object)(part.partInfo) != null) if ((object)(part.partInfo.partPrefab) != null) massDelta = part.mass - part.partInfo.partPrefab.mass; } // KIDS integration if (cfg.HasNode("atmosphereCurve")) { ConfigNode newCurveNode = new ConfigNode("atmosphereCurve"); FloatCurve oldCurve = new FloatCurve(); oldCurve.Load(cfg.GetNode("atmosphereCurve")); FloatCurve newCurve = Utilities.Mod(oldCurve, ispSLMult, ispVMult); newCurve.Save(newCurveNode); cfg.RemoveNode("atmosphereCurve"); cfg.AddNode(newCurveNode); } // gimbal change if (gimbal >= 0 && !cfg.HasValue("gimbalRange")) // if TL set a gimbal { // apply module-wide gimbal mult on top of any local ones cfg.AddValue("gimbalRange", (gimbal * gimbalMult).ToString("N4")); } if (cost != 0f) { if (cfg.HasValue("cost")) cfg.SetValue("cost", cost.ToString("N3")); else cfg.AddValue("cost", cost.ToString("N3")); } }
private string TLTInfo() { string retStr = ""; if (engineID != "") retStr += "Bound to " + engineID; if(moduleIndex >= 0) retStr += "Bound to engine " + moduleIndex + " in part"; if(techLevel != -1) { TechLevel cTL = new TechLevel(); if (!cTL.Load(config, techNodes, engineType, techLevel)) cTL = null; retStr = "Type: " + engineType + ". Tech Level: " + techLevel + " (" + origTechLevel + "-" + maxTechLevel + ")"; if (origMass > 0) retStr += ", Mass: " + part.mass.ToString("N3") + " (was " + (origMass * RFSettings.Instance.EngineMassMultiplier).ToString("N3") + ")"; if (configThrottle >= 0) retStr += ", MinThr " + (100f * configThrottle).ToString("N0") + "%"; float gimbalR = -1f; if (config.HasValue("gimbalRange")) gimbalR = float.Parse(config.GetValue("gimbalRange")); else if (!gimbalTransform.Equals("") || useGimbalAnyway) { if (cTL != null) gimbalR = cTL.GimbalRange; } if (gimbalR != -1f) retStr += ", Gimbal " + gimbalR.ToString("N1"); return retStr; } else return ""; }
private double ThrustTL(ConfigNode cfg = null) { if (techLevel != -1 && !engineType.Contains("S")) { TechLevel oldTL = new TechLevel(), newTL = new TechLevel(); if (!oldTL.Load(cfg == null ? config : cfg, techNodes, engineType, origTechLevel)) return 1.0; if (!newTL.Load(cfg == null ? config : cfg, techNodes, engineType, techLevel)) return 1.0; return newTL.Thrust(oldTL); } return 1.0; }
private float CostTL(float cost, ConfigNode cfg = null) { TechLevel cTL = new TechLevel(); TechLevel oTL = new TechLevel(); if (cTL.Load(cfg, techNodes, engineType, techLevel) && oTL.Load(cfg, techNodes, engineType, origTechLevel) && part.partInfo != null) { // Bit of a dance: we have to figure out the total cost of the part, but doing so // also depends on us. So we zero out our contribution first // and then restore configCost. float oldCC = configCost; configCost = 0f; float totalCost = part.partInfo.cost + part.GetModuleCosts(part.partInfo.cost); configCost = oldCC; cost = (totalCost + cost) * (cTL.CostMult / oTL.CostMult) - totalCost; } return cost; }
// MULTIPLIERS public double Thrust(TechLevel oldTL, bool constantMass = false) { if (oldTL.thrustMultiplier > 0 && thrustMultiplier > 0) return thrustMultiplier / oldTL.thrustMultiplier; if (constantMass) return TWR / oldTL.TWR; else return TWR / oldTL.TWR * oldTL.atmosphereCurve.Evaluate(0) / atmosphereCurve.Evaluate(0); }
public double Mass(TechLevel oldTL, bool constantThrust = false) { if (oldTL.massMultiplier > 0 && massMultiplier > 0) return massMultiplier / oldTL.massMultiplier; if (constantThrust) return oldTL.TWR / TWR; else return oldTL.atmosphereCurve.Evaluate(0) / atmosphereCurve.Evaluate(0); }
// Check if can switch to TL public static bool CanTL(ConfigNode cfg, ConfigNode mod, string type, int level) { TechLevel nTL = new TechLevel(); if (!nTL.Load(cfg, mod, type, level)) return false; return HighLogic.CurrentGame.Mode == Game.Modes.SANDBOX || nTL.techRequired.Equals("") || ResearchAndDevelopment.GetTechnologyState(nTL.techRequired) == RDTech.State.Available; }
public virtual void DoConfig(ConfigNode cfg) { // fix propellant ratios to not be rounded if (cfg.HasNode("PROPELLANT")) { foreach (ConfigNode pNode in cfg.GetNodes("PROPELLANT")) { if (pNode.HasValue("ratio")) { double dtmp; if (double.TryParse(pNode.GetValue("ratio"), out dtmp)) pNode.SetValue("ratio", (dtmp * 100.0).ToString()); } } } float heat = -1; if (cfg.HasValue("heatProduction")) // ohai amsi: allow heat production to be changed by multiplier { heat = (float)Math.Round(float.Parse(cfg.GetValue("heatProduction")) * heatMult, 0); cfg.SetValue("heatProduction", heat.ToString()); } // load throttle (for later) curThrottle = throttle; if (cfg.HasValue("throttle")) float.TryParse(cfg.GetValue("throttle"), out curThrottle); else if(cfg.HasValue("minThrust") && cfg.HasValue("maxThrust")) curThrottle = float.Parse(cfg.GetValue("minThrust")) / float.Parse(cfg.GetValue("maxThrust")); float TLMassMult = 1.0f; float gimbal = -1f; if (cfg.HasValue("gimbalRange")) gimbal = float.Parse(cfg.GetValue("gimbalRange")); float cost = 0f; if(cfg.HasValue("cost")) cost = float.Parse(cfg.GetValue("cost")); if (techLevel != -1) { // load techlevels TechLevel cTL = new TechLevel(); //print("For engine " + part.name + ", config " + configuration + ", max TL: " + TechLevel.MaxTL(cfg, techNodes, engineType)); cTL.Load(cfg, techNodes, engineType, techLevel); TechLevel oTL = new TechLevel(); oTL.Load(cfg, techNodes, engineType, origTechLevel); // set atmosphereCurve if (cfg.HasValue("IspSL") && cfg.HasValue("IspV")) { cfg.RemoveNode("atmosphereCurve"); ConfigNode curve = new ConfigNode("atmosphereCurve"); float ispSL, ispV; float.TryParse(cfg.GetValue("IspSL"), out ispSL); float.TryParse(cfg.GetValue("IspV"), out ispV); FloatCurve aC = new FloatCurve(); aC = Mod(cTL.AtmosphereCurve, ispSL, ispV); aC.Save(curve); cfg.AddNode(curve); } // set heatProduction and dissipation if (heat > 0) { cfg.SetValue("heatProduction", MassTL(heat).ToString("0")); part.heatDissipation = 0.12f / MassTL(1.0f); } // set thrust and throttle if (cfg.HasValue(thrustRating)) { float thr; float.TryParse(cfg.GetValue(thrustRating), out thr); configMaxThrust = ThrustTL(thr); cfg.SetValue(thrustRating, configMaxThrust.ToString("0.0000")); if (cfg.HasValue("minThrust")) { float.TryParse(cfg.GetValue("minThrust"), out thr); configMinThrust = ThrustTL(thr); cfg.SetValue("minThrust", configMinThrust.ToString("0.0000")); } else { if (thrustRating.Equals("thrusterPower")) { configMinThrust = configMaxThrust * 0.5f; } else { configMinThrust = configMaxThrust; if (curThrottle > 1.0f) { if (techLevel >= curThrottle) curThrottle = 1.0f; else curThrottle = -1.0f; } if (curThrottle >= 0.0f) { curThrottle = (float)((double)curThrottle * cTL.Throttle()); configMinThrust *= curThrottle; } cfg.SetValue("minThrust", configMinThrust.ToString("0.0000")); } } curThrottle = configMinThrust / configMaxThrust; if(origMass > 0) TLMassMult = MassTL(1.0f); } // Don't want to change gimbals on TL-enabled engines willy-nilly // So we don't unless either a transform is specified, or we override. // We assume if it was specified in the CONFIG that we should use it anyway. if (gimbal < 0 && (!gimbalTransform.Equals("") || useGimbalAnyway)) gimbal = cTL.GimbalRange; if (gimbal >= 0) { // allow local override of gimbal mult if (cfg.HasValue("gimbalMult")) gimbal *= float.Parse(cfg.GetValue("gimbalMult")); } // Cost (multiplier will be 1.0 if unspecified) cost = CostTL(cost, cfg); } else { if(cfg.HasValue(thrustRating) && curThrottle > 0f && !cfg.HasValue("minThrust")) { configMinThrust = curThrottle * float.Parse(cfg.GetValue(thrustRating)); cfg.SetValue("minThrust", configMinThrust.ToString("0.0000")); } } // mass change if (origMass > 0) { float ftmp; configMassMult = 1.0f; if (cfg.HasValue("massMult")) if (float.TryParse(cfg.GetValue("massMult"), out ftmp)) configMassMult = ftmp; part.mass = origMass * configMassMult * massMult * TLMassMult; massDelta = 0; if((object)(part.partInfo) != null) if((object)(part.partInfo.partPrefab) != null) massDelta = part.mass - part.partInfo.partPrefab.mass; } // KIDS integration if(cfg.HasNode("atmosphereCurve")) { ConfigNode newCurveNode = new ConfigNode("atmosphereCurve"); FloatCurve oldCurve = new FloatCurve(); oldCurve.Load(cfg.GetNode("atmosphereCurve")); FloatCurve newCurve = Mod(oldCurve, ispSLMult, ispVMult); newCurve.Save(newCurveNode); cfg.RemoveNode("atmosphereCurve"); cfg.AddNode(newCurveNode); } // gimbal change if (gimbal >= 0 && !cfg.HasValue("gimbalRange")) // if TL set a gimbal { // apply module-wide gimbal mult on top of any local ones cfg.AddValue("gimbalRange", (gimbal * gimbalMult).ToString("N4")); } if (cost != 0f) { if (cfg.HasValue("cost")) cfg.SetValue("cost", cost.ToString("N3")); else cfg.AddValue("cost", cost.ToString("N3")); } }
public string GetConfigInfo(ConfigNode config) { TechLevel cTL = new TechLevel(); if (!cTL.Load(config, techNodes, engineType, techLevel)) cTL = null; string info = " " + config.GetValue("name") + "\n"; if (config.HasValue("description")) info += " " + config.GetValue("description") + "\n"; if (config.HasValue(thrustRating)) { info += " " + (scale * ThrustTL(config.GetValue(thrustRating), config)).ToString("G3") + " kN"; // add throttling info if present if (config.HasValue("minThrust")) info += ", min " + (float.Parse(config.GetValue("minThrust")) / float.Parse(config.GetValue(thrustRating)) * 100f).ToString("N0") + "%"; else if (config.HasValue("throttle")) info += ", min " + (float.Parse(config.GetValue("throttle")) * 100f).ToString("N0") + "%"; } else info += " Unknown Thrust"; if (origMass > 0f) { float cMass = scale; float ftmp; if (config.HasValue("massMult")) if (float.TryParse(config.GetValue("massMult"), out ftmp)) cMass *= ftmp; cMass = origMass * cMass * RFSettings.Instance.EngineMassMultiplier; info += ", " + cMass.ToString("N3") + "t"; } info += "\n"; FloatCurve isp = new FloatCurve(); if (config.HasNode("atmosphereCurve")) { isp.Load(config.GetNode("atmosphereCurve")); info += " Isp: " + isp.Evaluate(isp.maxTime).ToString() + " - " + isp.Evaluate(isp.minTime).ToString() + "s\n"; } else if (config.HasValue("IspSL") && config.HasValue("IspV")) { float ispSL = 1.0f, ispV = 1.0f; float.TryParse(config.GetValue("IspSL"), out ispSL); float.TryParse(config.GetValue("IspV"), out ispV); if (cTL != null) { ispSL *= ispSLMult * cTL.AtmosphereCurve.Evaluate(1); ispV *= ispVMult * cTL.AtmosphereCurve.Evaluate(0); info += " Isp: " + ispSL.ToString("0") + " - " + ispV.ToString("0") + "s\n"; } } float gimbalR = -1f; if (config.HasValue("gimbalRange")) gimbalR = float.Parse(config.GetValue("gimbalRange")); // Don't do per-TL checks here, they're misleading. /*else if (!gimbalTransform.Equals("") || useGimbalAnyway) { if (cTL != null) gimbalR = cTL.GimbalRange; }*/ if (gimbalR != -1f) info += " Gimbal " + gimbalR.ToString("N1") + "d\n"; if (config.HasValue("ullage") || config.HasValue("ignitions") || config.HasValue("pressureFed")) { info += " "; bool comma = false; if (config.HasValue("ullage")) { info += (config.GetValue("ullage").ToLower() == "true" ? "ullage" : "no ullage"); comma = true; } if (config.HasValue("pressureFed") && config.GetValue("pressureFed").ToLower() == "true") { if (comma) info += ", "; info += "pfed"; comma = true; } if (config.HasValue("ignitions")) { int ignitions; if (int.TryParse(config.GetValue("ignitions"), out ignitions)) { if (comma) info += ", "; if (ignitions > 0) info += ignitions + " ignition" + (ignitions > 1 ? "s" : ""); else info += "unl. ignitions"; } } info += "\n"; } float cst; if (config.HasValue("cost") && float.TryParse(config.GetValue("cost"), out cst)) info += " (" + (scale * cst).ToString("N0") + " extra cost)\n"; // FIXME should get cost from TL, but this should be safe return info; }
//TODO public virtual void DoDEVConfig(ConfigNode cfg) { float TLMassMult = 1.0f; float gimbal = -1f; if (cfg.HasValue("gimbalRange")) gimbal = float.Parse(cfg.GetValue("gimbalRange")); float cost = 0f; if (cfg.HasValue("cost")) cost = scale * float.Parse(cfg.GetValue("cost")); if (techLevel != -1) { // load techlevels TechLevel cTL = new TechLevel(); cTL.Load(cfg, techNodes, engineType, techLevel); TechLevel oTL = new TechLevel(); oTL.Load(cfg, techNodes, engineType, origTechLevel); // set heatProduction if (configHeat > 0) { configHeat = MassTL(configHeat); } // Don't want to change gimbals on TL-enabled engines willy-nilly // So we don't unless either a transform is specified, or we override. // We assume if it was specified in the CONFIG that we should use it anyway. if (gimbal < 0 && (!gimbalTransform.Equals("") || useGimbalAnyway)) gimbal = cTL.GimbalRange; if (gimbal >= 0) { // allow local override of gimbal mult if (cfg.HasValue("gimbalMult")) gimbal *= float.Parse(cfg.GetValue("gimbalMult")); } // Cost (multiplier will be 1.0 if unspecified) cost = scale * CostTL(cost, cfg); } else { if (cfg.HasValue(thrustRating) && configThrottle > 0f && !cfg.HasValue("minThrust")) { configMinThrust = configThrottle * configMaxThrust; } } // heat update if (configHeat >= 0f) cfg.SetValue("heatProduction", configHeat.ToString("0")); // mass change if (origMass > 0) { float ftmp; configMassMult = scale; if (cfg.HasValue("massMult")) if (float.TryParse(cfg.GetValue("massMult"), out ftmp)) configMassMult *= ftmp; part.mass = origMass * configMassMult * RFSettings.Instance.EngineMassMultiplier * TLMassMult; massDelta = 0; if ((object)(part.partInfo) != null) if ((object)(part.partInfo.partPrefab) != null) massDelta = part.mass - part.partInfo.partPrefab.mass; } // gimbal change if (gimbal >= 0 && !cfg.HasValue("gimbalRange")) // if TL set a gimbal { // apply module-wide gimbal mult on top of any local ones cfg.AddValue("gimbalRange", (gimbal * gimbalMult).ToString("N4")); } if (cost != 0f) { if (cfg.HasValue("cost")) cfg.SetValue("cost", cost.ToString("N3")); else cfg.AddValue("cost", cost.ToString("N3")); } }