public override void OnStart(PartModule.StartState state) { if (state == StartState.Editor) { return; } bool manual_upgrade = false; if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) { if (upgradeTechReq != null) { if (PluginHelper.hasTech(upgradeTechReq)) { hasrequiredupgrade = true; } else if (upgradeTechReq == "none") { manual_upgrade = true; } } else { manual_upgrade = true; } } else { hasrequiredupgrade = true; } if (coreInit == false) { coreInit = true; if (hasrequiredupgrade) { isupgraded = true; } } if (manual_upgrade) { hasrequiredupgrade = true; } if (isupgraded) { computercoreType = upgradedName; if (nameStr == "") { ConfigNode[] namelist = ComputerCore.getNames(); Random rands = new Random(); ConfigNode myName = namelist[rands.Next(0, namelist.Length)]; nameStr = myName.GetValue("name"); } double now = Planetarium.GetUniversalTime(); double time_diff = now - last_active_time; float altitude_multiplier = (float)(vessel.altitude / (vessel.mainBody.Radius)); altitude_multiplier = Math.Max(altitude_multiplier, 1); double science_to_add = baseScienceRate * time_diff / 86400 * electrical_power_ratio * PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed) / ((float)Math.Sqrt(altitude_multiplier)); science_awaiting_addition = science_to_add; var curReaction = this.part.Modules["ModuleReactionWheel"] as ModuleReactionWheel; curReaction.PitchTorque = 5; curReaction.RollTorque = 5; curReaction.YawTorque = 5; } else { computercoreType = originalName; } this.part.force_activate(); }
public override void OnUpdate() { bool inAtmos = false; if (vessel.altitude <= PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody)) { telescopeIsEnabled = false; inAtmos = true; } Events["beginOberservations"].active = !inAtmos && !telescopeIsEnabled; Events["stopOberservations"].active = telescopeIsEnabled; Fields["sciencePerDay"].guiActive = telescopeIsEnabled; performPcnt = (perform_factor_d * 100).ToString("0.0") + "%"; sciencePerDay = (science_rate * 86400).ToString("0.00") + " Science/Day"; double current_au = Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position) / Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position); if (vessel.FindPartModulesImplementing <ScienceModule>().Count > 0 || vessel.FindPartModulesImplementing <ComputerCore>().Count > 0) { List <ComputerCore> cores = vessel.FindPartModulesImplementing <ComputerCore>(); List <ScienceModule> science_labs = vessel.FindPartModulesImplementing <ScienceModule>(); bool upgraded_core = false; bool crewed_lab = false; foreach (ComputerCore core in cores) { upgraded_core = upgraded_core ? upgraded_core : core.isupgraded; } foreach (ScienceModule science_lab in science_labs) { crewed_lab = crewed_lab ? crewed_lab : (science_lab.part.protoModuleCrew.Count > 0); } if (current_au >= 548 && !inAtmos && (crewed_lab || upgraded_core)) { if (vessel.orbit.eccentricity < 0.8) { Events["beginOberservations2"].active = true; if (telescopeIsEnabled && dpo) { gLensStr = "Ongoing."; } else { gLensStr = "Available."; } } else { Events["beginOberservations2"].active = false; gLensStr = "Eccentricity: " + vessel.orbit.eccentricity.ToString("0.0") + "; < 0.8 Required"; } } else { Events["beginOberservations2"].active = false; gLensStr = current_au.ToString("0.0") + " AU; Required 548 AU"; } } else { Events["beginOberservations2"].active = false; gLensStr = "Science Lab/Computer Core required"; } if (helium_time_scale <= 0) { performPcnt = "Helium Coolant Deprived."; } }
private void UpdateAmounts() { capacityStr = PluginHelper.formatMassStr(antimatterResource.amount * antimatterDensity); maxAmountStr = PluginHelper.formatMassStr(antimatterResource.maxAmount * antimatterDensity); }
public static bool HasTechRequirementAndNotEmpty(string techName) { return(techName != String.Empty && PluginHelper.upgradeAvailable(techName)); }
public void onVesselAboutToBeDestroyed(EventReport report) { Debug.Log("[KSP Interstellar] Handling Impactor"); ConfigNode config; ConfigNode science_node; Vessel vessel = report.origin.vessel; float vesselMass; int science_experiment_number = 0; string vessel_impact_node_string = string.Concat("IMPACT_", vessel.id.ToString()); string vessel_seismic_node_string = string.Concat("SEISMIC_SCIENCE_", vessel.mainBody.name.ToUpper()); // Do nothing if we don't have a vessel. This seems improbable, but who knows. if (vessel == null) { Debug.Log("[KSP Interstellar] Impactor: Ignored because the vessel is undefined."); return; } // Do nothing if we have recorded an impact less than 10 physics updates ago. This probably means this call // is a duplicate of a previous call. if (Planetarium.GetUniversalTime() - this.lastImpactTime < TimeWarp.fixedDeltaTime * 10f) { Debug.Log("[KSP Interstellar] Impactor: Ignored because we've just recorded an impact."); return; } // Do nothing if we are a debris item less than ten physics-updates old. That probably means we were // generated by a recently-recorded impact. if (vessel.vesselType == VesselType.Debris && vessel.missionTime < Time.fixedDeltaTime * 10f) { Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel being brand-new debris."); return; } vesselMass = vessel.GetTotalMass(); // Do nothing if we aren't very near the terrain. Note that using heightFromTerrain probably allows // impactors against the ocean floor... good luck. float vesselDimension = vessel.MOI.magnitude / vesselMass; if (vessel.heightFromSurface > Mathf.Max(vesselDimension, 0.75f)) { Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel altitude being too high."); return; } // Do nothing if we aren't impacting the surface. if (!( report.other.ToLower().Contains(string.Intern("surface")) || report.other.ToLower().Contains(string.Intern("terrain")) || report.other.ToLower().Contains(vessel.mainBody.name.ToLower()) )) { Debug.Log("[KSP Interstellar] Impactor: Ignored due to not impacting the surface."); return; } /* * NOTE: This is a deviation from current KSPI behavior. KSPI currently registers an impact over 40 m/s * regardless of its mass; this means that trivially light impactors (single instruments, even) could * trigger the experiment. * * The guard below requires that the impactor have at least as much vertical impact energy as a 1 Mg * object traveling at 40 m/s. This means that nearly-tangential impacts or very light impactors will need * to be much faster, but that heavier impactors may be slower. * * */ if ((Math.Pow(vessel.verticalSpeed, 2d) * vesselMass / 2d < 800d) && vessel.verticalSpeed > 20d) { Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel imparting too little impact energy."); return; } config = PluginHelper.getPluginSaveFile(); if (config.HasNode(vessel_seismic_node_string)) { science_node = config.GetNode(vessel_seismic_node_string); science_experiment_number = science_node.nodes.Count; if (science_node.HasNode(vessel_impact_node_string)) { Debug.Log("[KSP Interstellar] Impactor: Ignored because this vessel's impact has already been recorded."); return; } } else { science_node = config.AddNode(vessel_seismic_node_string); science_node.AddValue("name", "interstellarseismicarchive"); } int body = vessel.mainBody.flightGlobalsIndex; Vector3d net_vector = Vector3d.zero; bool first = true; double distribution_factor = 0; foreach (Vessel conf_vess in FlightGlobals.Vessels) { String vessel_probe_node_string = string.Concat("VESSEL_SEISMIC_PROBE_", conf_vess.id.ToString()); if (config.HasNode(vessel_probe_node_string)) { ConfigNode probe_node = config.GetNode(vessel_probe_node_string); // If the seismometer is inactive, skip it. bool is_active = false; if (probe_node.HasValue("is_active")) { bool.TryParse(probe_node.GetValue("is_active"), out is_active); if (!is_active) { continue; } } // If the seismometer is on another planet, skip it. int planet = -1; if (probe_node.HasValue("celestial_body")) { int.TryParse(probe_node.GetValue("celestial_body"), out planet); if (planet != body) { continue; } } // do sciency stuff Vector3d surface_vector = (conf_vess.transform.position - FlightGlobals.Bodies[body].transform.position); surface_vector = surface_vector.normalized; if (first) { first = false; net_vector = surface_vector; distribution_factor = 1; } else { distribution_factor += 1.0 - Vector3d.Dot(surface_vector, net_vector.normalized); net_vector = net_vector + surface_vector; } } } distribution_factor = Math.Min(distribution_factor, 3.5); // no more than 3.5x boost to science by using multiple detectors if (distribution_factor > 0 && !double.IsInfinity(distribution_factor) && !double.IsNaN(distribution_factor)) { ScreenMessages.PostScreenMessage("Impact Recorded, science report can now be accessed from one of your accelerometers deployed on this body.", 5f, ScreenMessageStyle.UPPER_CENTER); this.lastImpactTime = Planetarium.GetUniversalTime(); Debug.Log("[KSP Interstellar] Impactor: Impact registered!"); ConfigNode impact_node = new ConfigNode(vessel_impact_node_string); impact_node.AddValue(string.Intern("transmitted"), bool.FalseString); impact_node.AddValue(string.Intern("vesselname"), vessel.vesselName); impact_node.AddValue(string.Intern("distribution_factor"), distribution_factor); science_node.AddNode(impact_node); config.Save(PluginHelper.PluginSaveFilePath); } }
private void ScoopAthmosphere(double deltaTimeInSeconds, bool offlineCollecting) { string ors_atmospheric_resource_name = AtmosphericResourceHandler.getAtmosphericResourceName(vessel.mainBody, currentresource); string resourceDisplayName = AtmosphericResourceHandler.getAtmosphericResourceDisplayName(vessel.mainBody, currentresource); if (ors_atmospheric_resource_name == null) { resflowf = 0; recievedPower = "error"; densityFractionOfUpperAthmosphere = "error"; return; } // map ors resource to kspi resource if (PluginHelper.OrsResourceMappings == null || !PluginHelper.OrsResourceMappings.TryGetValue(ors_atmospheric_resource_name, out resourceStoragename)) { resourceStoragename = ors_atmospheric_resource_name; } else if (!PartResourceLibrary.Instance.resourceDefinitions.Contains(resourceStoragename)) { resourceStoragename = ors_atmospheric_resource_name; } var definition = PartResourceLibrary.Instance.GetDefinition(resourceStoragename); if (definition == null) { return; } double resourcedensity = (double)(decimal)definition.density; double maxAltitudeAtmosphere = PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody); double upperAtmospherFraction = Math.Max(0, (vessel.altitude - maxAltitudeAtmosphere) / Math.Max(0.000001, maxAltitudeAtmosphere * PluginHelper.MaxAtmosphericAltitudeMult - maxAltitudeAtmosphere)); double upperatmosphereDensity = 1 - upperAtmospherFraction; double airDensity = part.vessel.atmDensity + (PluginHelper.MinAtmosphericAirDensity * upperatmosphereDensity); atmosphericDensity = airDensity.ToString("0.00000000"); var hydrogenTax = 0.4 * Math.Sin(upperAtmospherFraction * Math.PI * 0.5); var heliumTax = 0.2 * Math.Sin(upperAtmospherFraction * Math.PI); double rescourceFraction = (1.0 - hydrogenTax - heliumTax) * AtmosphericResourceHandler.getAtmosphericResourceContent(vessel.mainBody, currentresource); // increase density hydrogen if (resourceDisplayName == "Hydrogen") { rescourceFraction += hydrogenTax; } else if (resourceDisplayName == "Helium") { rescourceFraction += heliumTax; } densityFractionOfUpperAthmosphere = (upperatmosphereDensity * 100).ToString("0.000") + "%"; rescourcePercentage = rescourceFraction * 100; if (rescourceFraction <= 0 || vessel.altitude > (PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody) * PluginHelper.MaxAtmosphericAltitudeMult)) { resflowf = 0; recievedPower = "off"; densityFractionOfUpperAthmosphere = "too high"; rescourcePercentage = 0; return; } double airspeed = part.vessel.srf_velocity.magnitude + 40; double air = airspeed * (airDensity / 1000) * scoopair / resourcedensity; double scoopedAtm = air * rescourceFraction; double powerrequirementsMW = (scoopair / 0.15) * 6 * PluginHelper.PowerConsumptionMultiplier * powerReqMult; if (scoopedAtm > 0 && part.GetResourceSpareCapacity(resourceStoragename) > 0) { var powerRequest = powerrequirementsMW * TimeWarp.fixedDeltaTime; // calculate available power double powerreceivedMW = CheatOptions.InfiniteElectricity ? powerRequest : Math.Max(consumeFNResource(powerRequest, ResourceManager.FNRESOURCE_MEGAJOULES, TimeWarp.fixedDeltaTime), 0); double normalisedRevievedPowerMW = powerreceivedMW / TimeWarp.fixedDeltaTime; // if power requirement sufficiently low, retreive power from KW source if (powerrequirementsMW < 2 && normalisedRevievedPowerMW <= powerrequirementsMW) { var requiredKW = (powerrequirementsMW - normalisedRevievedPowerMW) * 1000; var recievedKW = part.RequestResource(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, requiredKW * TimeWarp.fixedDeltaTime); powerreceivedMW += (recievedKW / 1000); } last_power_percentage = offlineCollecting ? last_power_percentage : powerreceivedMW / powerrequirementsMW / TimeWarp.fixedDeltaTime; } else { last_power_percentage = 0; powerrequirementsMW = 0; } recievedPower = powerrequirementsMW < 2 ? (last_power_percentage * powerrequirementsMW * 1000).ToString("0.0") + " KW / " + (powerrequirementsMW * 1000).ToString("0.0") + " KW" : (last_power_percentage * powerrequirementsMW).ToString("0.0") + " MW / " + powerrequirementsMW.ToString("0.0") + " MW"; double resourceChange = scoopedAtm * last_power_percentage * deltaTimeInSeconds; if (offlineCollecting) { string numberformat = resourceChange > 100 ? "0" : "0.00"; ScreenMessages.PostScreenMessage("Atmospheric Scoop collected " + resourceChange.ToString(numberformat) + " " + resourceStoragename, 10.0f, ScreenMessageStyle.LOWER_CENTER); } resflowf = part.RequestResource(resourceStoragename, -resourceChange); resflowf = -resflowf / TimeWarp.fixedDeltaTime; UpdateResourceFlow(); }
public override void OnUpdate() { base.OnUpdate(); if (ResearchAndDevelopment.Instance != null) { Events["RetrofitCore"].active = !isupgraded && ResearchAndDevelopment.Instance.Science >= upgradeCost; } else { Events["RetrofitCore"].active = false; } Fields["upgradeCostStr"].guiActive = !isupgraded; Fields["nameStr"].guiActive = isupgraded; Fields["scienceRate"].guiActive = isupgraded; float scienceratetmp = (float)(science_rate_f * GameConstants.KEBRIN_DAY_SECONDS) * PluginHelper.getScienceMultiplier(vessel); scienceRate = scienceratetmp.ToString("0.000") + "/Day"; if (ResearchAndDevelopment.Instance != null) { upgradeCostStr = ResearchAndDevelopment.Instance.Science + "/" + upgradeCost.ToString("0") + " Science"; } }
protected override bool generateScienceData() { ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment("FNSeismicProbeExperiment"); if (experiment == null) { return(false); } //ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.SrfLanded, vessel.mainBody, "surface"); //if (subject == null) { // return false; //} //subject.scientificValue = 1; //subject.scienceCap = float.MaxValue; //subject.science = 1; //subject.subjectValue = 1; result_title = "Impactor Experiment"; result_string = "No useful seismic data has been recorded."; transmit_value = 0; recovery_value = 0; data_size = 0; xmit_scalar = 1; ref_value = 1; // science_data = new ScienceData(0, 1, 0, subject.id, "data"); ConfigNode config = PluginHelper.getPluginSaveFile(); if (config.HasNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper())) { ConfigNode planet_data = config.GetNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper()); foreach (ConfigNode probe_data in planet_data.nodes) { if (probe_data.name.Contains("IMPACT_")) { science_vess_ref = probe_data.name; bool transmitted = false; string vessel_name = ""; float science_amount = 0; int exp_number = 1; if (probe_data.HasValue("transmitted")) { transmitted = bool.Parse(probe_data.GetValue("transmitted")); } if (probe_data.HasValue("vesselname")) { vessel_name = probe_data.GetValue("vesselname"); } if (probe_data.HasValue("science")) { science_amount = float.Parse(probe_data.GetValue("science")); } if (probe_data.HasValue("number")) { exp_number = int.Parse(probe_data.GetValue("number")); } if (!transmitted) { ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.SrfLanded, vessel.mainBody, vessel.mainBody.name + "'s surface."); if (subject == null) { return(false); } result_string = vessel_name + " impacted into " + vessel.mainBody.name + " producing seismic activity. From this data, information on the structure of " + vessel.mainBody.name + "'s crust can be determined."; transmit_value = science_amount; recovery_value = science_amount; subject.subjectValue = 1; subject.scientificValue = 1; subject.scienceCap = 50 * 10 * PluginHelper.getScienceMultiplier(vessel); //PluginHelper.getImpactorScienceMultiplier(vessel.mainBody.flightGlobalsIndex); //subject.science = 0; data_size = science_amount * 2.5f; science_data = new ScienceData(science_amount, 1, 0, subject.id, "Impactor Data"); ref_value = 50 * PluginHelper.getScienceMultiplier(vessel); // PluginHelper.getImpactorScienceMultiplier(vessel.mainBody.flightGlobalsIndex); return(true); } } } } return(false); }
public override void OnUpdate() { base.OnUpdate(); Events["BeginResearch"].active = isupgraded && !IsEnabled; Events["ReprocessFuel"].active = !IsEnabled; Events["ActivateFactory"].active = isupgraded && !IsEnabled; Events["ActivateElectrolysis"].active = false; Events["ActivateCentrifuge"].active = isupgraded && !IsEnabled && vessel.Splashed; Events["StopActivity"].active = isupgraded && IsEnabled; Fields["statusTitle"].guiActive = isupgraded; // only show retrofit btoon if we can actualy upgrade Events["RetrofitEngine"].active = ResearchAndDevelopment.Instance == null ? false : !isupgraded && ResearchAndDevelopment.Instance.Science >= upgradeCost && hasrequiredupgrade; if (IsEnabled) { //anim [animName1].normalizedTime = 1f; statusTitle = modes[active_mode] + "..."; Fields["scienceRate"].guiActive = false; Fields["collectedScience"].guiActive = false; Fields["reprocessingRate"].guiActive = false; Fields["antimatterRate"].guiActive = false; Fields["electrolysisRate"].guiActive = false; Fields["centrifugeRate"].guiActive = false; Fields["antimatterProductionEfficiency"].guiActive = false; Fields["powerStr"].guiActive = true; double currentpowertmp = electrical_power_ratio * PluginHelper.BasePowerConsumption * powerReqMult; powerStr = currentpowertmp.ToString("0.0000") + "MW / " + (powerReqMult * PluginHelper.BasePowerConsumption).ToString("0.0000") + "MW"; if (active_mode == 0) // Research { Fields["scienceRate"].guiActive = true; Fields["collectedScience"].guiActive = true; double scienceratetmp = science_rate_f * PluginHelper.SecondsInDay * PluginHelper.getScienceMultiplier(vessel); scienceRate = scienceratetmp.ToString("0.0000") + "/Day"; collectedScience = science_to_add.ToString("0.000000"); } else if (active_mode == 1) // Fuel Reprocessing { Fields["reprocessingRate"].guiActive = true; reprocessingRate = reprocessing_rate_f.ToString("0.0") + " Hours Remaining"; } else if (active_mode == 2) // Antimatter { currentpowertmp = electrical_power_ratio * PluginHelper.BaseAMFPowerConsumption * powerReqMult; Fields["antimatterRate"].guiActive = true; Fields["antimatterProductionEfficiency"].guiActive = true; powerStr = currentpowertmp.ToString("0.00") + "MW / " + (powerReqMult * PluginHelper.BaseAMFPowerConsumption).ToString("0.00") + "MW"; antimatterProductionEfficiency = (anti_factory.getAntimatterProductionEfficiency() * 100).ToString("0.0000") + "%"; double antimatter_rate_per_day = antimatter_rate_f * PluginHelper.SecondsInDay; if (antimatter_rate_per_day > 0.1) { antimatterRate = (antimatter_rate_per_day).ToString("0.0000") + " mg/day"; } else { if (antimatter_rate_per_day > 0.1e-3) { antimatterRate = (antimatter_rate_per_day * 1e3).ToString("0.0000") + " ug/day"; } else { antimatterRate = (antimatter_rate_per_day * 1e6).ToString("0.0000") + " ng/day"; } } } else if (active_mode == 3) // Electrolysis { currentpowertmp = electrical_power_ratio * PluginHelper.BaseELCPowerConsumption * powerReqMult; Fields["electrolysisRate"].guiActive = true; double electrolysisratetmp = -electrolysis_rate_f * PluginHelper.SecondsInDay; electrolysisRate = electrolysisratetmp.ToString("0.0") + "mT/day"; powerStr = currentpowertmp.ToString("0.00") + "MW / " + (powerReqMult * PluginHelper.BaseELCPowerConsumption).ToString("0.00") + "MW"; } else if (active_mode == 4) // Centrifuge { currentpowertmp = electrical_power_ratio * PluginHelper.BaseCentriPowerConsumption * powerReqMult; Fields["centrifugeRate"].guiActive = true; powerStr = currentpowertmp.ToString("0.00") + "MW / " + (powerReqMult * PluginHelper.BaseCentriPowerConsumption).ToString("0.00") + "MW"; double deut_per_hour = deut_rate_f * 3600; centrifugeRate = deut_per_hour.ToString("0.00") + " Kg Deuterium/Hour"; } else { // nothing } } else { if (play_down) { anim[animName1].speed = -1; anim[animName1].normalizedTime = 1; anim.Blend(animName1, 2); anim2[animName2].speed = -1; anim2[animName2].normalizedTime = 1; anim2.Blend(animName2, 2); play_down = false; } //anim [animName1].normalizedTime = 0; Fields["scienceRate"].guiActive = false; Fields["collectedScience"].guiActive = false; Fields["reprocessingRate"].guiActive = false; Fields["antimatterRate"].guiActive = false; Fields["powerStr"].guiActive = false; Fields["centrifugeRate"].guiActive = false; Fields["electrolysisRate"].guiActive = false; Fields["antimatterProductionEfficiency"].guiActive = false; if (crew_capacity_ratio > 0) { statusTitle = "Idle"; } else { statusTitle = "Not enough crew"; } } }
public override void OnStart(PartModule.StartState state) { String[] resources_to_supply = { FNResourceManager.FNRESOURCE_MEGAJOULES, FNResourceManager.FNRESOURCE_WASTEHEAT, FNResourceManager.FNRESOURCE_THERMALPOWER }; this.resources_to_supply = resources_to_supply; base.OnStart(state); if (state == StartState.Editor) { return; } if (part.FindModulesImplementing <MicrowavePowerTransmitter>().Count == 1) { part_transmitter = part.FindModulesImplementing <MicrowavePowerTransmitter>().First(); has_transmitter = true; } if (animTName != null) { animT = part.FindModelAnimators(animTName).FirstOrDefault(); if (animT != null) { animT[animTName].layer = 1; animT[animTName].normalizedTime = 0f; animT[animTName].speed = 0.001f; animT.Play(); } } if (animName != null) { anim = part.FindModelAnimators(animName).FirstOrDefault(); if (anim != null) { anim[animName].layer = 1; if (connectedsatsi > 0 || connectedrelaysi > 0) { anim[animName].normalizedTime = 1f; anim[animName].speed = -1f; } else { anim[animName].normalizedTime = 0f; anim[animName].speed = 1f; } anim.Play(); } } vmps = new List <VesselMicrowavePersistence>(); vrps = new List <VesselRelayPersistence>(); foreach (Vessel vess in FlightGlobals.Vessels) { String vesselID = vess.id.ToString(); if (vess.isActiveVessel == false && vess.vesselName.ToLower().IndexOf("debris") == -1) { ConfigNode config = PluginHelper.getPluginSaveFile(); if (config.HasNode("VESSEL_MICROWAVE_POWER_" + vesselID)) { ConfigNode power_node = config.GetNode("VESSEL_MICROWAVE_POWER_" + vesselID); double nuclear_power = 0; double solar_power = 0; if (power_node.HasValue("nuclear_power")) { nuclear_power = double.Parse(power_node.GetValue("nuclear_power")); } if (power_node.HasValue("solar_power")) { solar_power = double.Parse(power_node.GetValue("solar_power")); } if (nuclear_power > 0 || solar_power > 0) { VesselMicrowavePersistence vmp = new VesselMicrowavePersistence(vess); vmp.setSolarPower(solar_power); vmp.setNuclearPower(nuclear_power); vmps.Add(vmp); } } if (config.HasNode("VESSEL_MICROWAVE_RELAY_" + vesselID)) { ConfigNode relay_node = config.GetNode("VESSEL_MICROWAVE_RELAY_" + vesselID); if (relay_node.HasValue("relay")) { bool relay = bool.Parse(relay_node.GetValue("relay")); if (relay) { VesselRelayPersistence vrp = new VesselRelayPersistence(vess); vrp.setActive(relay); vrps.Add(vrp); } } } } } penaltyFreeDistance = Math.Sqrt(1 / ((microwaveAngleTan * microwaveAngleTan) / collectorArea)); this.part.force_activate(); }
public static List <ElectricEnginePropellant> GetPropellantsEngineForType(int type) { ConfigNode[] propellantlist = GameDatabase.Instance.GetConfigNodes("ELECTRIC_PROPELLANT"); List <ElectricEnginePropellant> propellant_list; if (propellantlist.Length == 0) { PluginHelper.showInstallationErrorMessage(); propellant_list = new List <ElectricEnginePropellant>(); } else { propellant_list = propellantlist.Select(prop => new ElectricEnginePropellant(prop)) .Where(eep => (eep.SupportedEngines & type) == type && PluginHelper.HasTechRequirementOrEmpty(eep.TechRequirement)).ToList(); } // initialize resource Defnitionions foreach (var propellant in propellant_list) { propellant.resourceDefinition = PartResourceLibrary.Instance.GetDefinition(propellant.propellant.name); } return(propellant_list); }
/// <summary> /// Returns transmitters which to which this vessel can connect, route efficiency and relays used for each one. /// </summary> /// <param name="maxHops">Maximum number of relays which can be used for connection to transmitter</param> protected IDictionary <VesselMicrowavePersistence, KeyValuePair <double, IEnumerable <VesselRelayPersistence> > > GetConnectedTransmitters(int maxHops = 25) { //these two dictionaries store transmitters and relays and best currently known route to them which is replaced if better one is found. var transmitterRouteDictionary = new Dictionary <VesselMicrowavePersistence, MicrowaveRoute>(); // stores all transmitter we can have a connection with var relayRouteDictionary = new Dictionary <VesselRelayPersistence, MicrowaveRoute>(); var transmittersToCheck = new List <VesselMicrowavePersistence>();//stores all transmiters to which we want to connect foreach (VesselMicrowavePersistence transmitter in MicrowaveSources.instance.transmitters.Values) { //first check for direct connection from current vessel to transmitters, will always be optimal if (transmitter.getAvailablePower() <= 0) { continue; } // get transmitting vessel var transmitterVessel = transmitter.getVessel(); //ignore if no power or transmitter is on the same vessel if (isInlineReceiver && transmitterVessel == vessel) { continue; } if (PluginHelper.HasLineOfSightWith(this.vessel, transmitterVessel)) { double distance = ComputeDistance(this.vessel, transmitterVessel); double facingFactor = ComputeFacingFactor(transmitterVessel); double distanceFacingEfficiency = ComputeDistanceFacingEfficiency(distance, facingFactor); double atmosphereEfficency = GetAtmosphericEfficiency(transmitterVessel); double transmitterEfficency = distanceFacingEfficiency * atmosphereEfficency; transmitterRouteDictionary[transmitter] = new MicrowaveRoute(transmitterEfficency, distance, facingFactor); //store in dictionary that optimal route to this transmitter is direct connection, can be replaced if better route is found } transmittersToCheck.Add(transmitter); } //this algorithm processes relays in groups in which elements of the first group must be visible from receiver, //elements from the second group must be visible by at least one element from previous group and so on... var relaysToCheck = new List <VesselRelayPersistence>(); //relays which we have to check - all active relays will be here var currentRelayGroup = new List <KeyValuePair <VesselRelayPersistence, int> >(); //relays which are in line of sight, and we have not yet checked what they can see. Their index in relaysToCheck is also stored int relayIndex = 0; foreach (VesselRelayPersistence relay in MicrowaveSources.instance.relays.Values) { if (!relay.isActive()) { continue; } var relayVessel = relay.getVessel(); //if (lineOfSightTo(relay.getVessel())) if (PluginHelper.HasLineOfSightWith(this.vessel, relayVessel)) { double distance = ComputeDistance(vessel, relayVessel); double facingFactor = ComputeFacingFactor(relayVessel); double distanceFacingEfficiency = ComputeDistanceFacingEfficiency(distance, facingFactor); double atmosphereEfficency = GetAtmosphericEfficiency(relayVessel); double transmitterEfficency = distanceFacingEfficiency * atmosphereEfficency; relayRouteDictionary[relay] = new MicrowaveRoute(transmitterEfficency, distance, facingFactor);//store in dictionary that optimal route to this relay is direct connection, can be replaced if better route is found currentRelayGroup.Add(new KeyValuePair <VesselRelayPersistence, int>(relay, relayIndex)); } relaysToCheck.Add(relay); relayIndex++; } int hops = 0; //number of hops between relays //pre-compute distances and visibility thus limiting number of checks to (Nr^2)/2 + NrNt +Nr + Nt if (hops < maxHops && transmittersToCheck.Any()) { double[,] relayToRelayDistances = new double[relaysToCheck.Count, relaysToCheck.Count]; double[,] relayToTransmitterDistances = new double[relaysToCheck.Count, transmittersToCheck.Count]; for (int i = 0; i < relaysToCheck.Count; i++) { var relay = relaysToCheck[i]; for (int j = i + 1; j < relaysToCheck.Count; j++) { double visibilityAndDistance = ComputeVisibilityAndDistance(relay, relaysToCheck[j].getVessel()); relayToRelayDistances[i, j] = visibilityAndDistance; relayToRelayDistances[j, i] = visibilityAndDistance; } for (int t = 0; t < transmittersToCheck.Count; t++) { relayToTransmitterDistances[i, t] = ComputeVisibilityAndDistance(relay, transmittersToCheck[t].getVessel()); } } HashSet <int> coveredRelays = new HashSet <int>(); //runs as long as there is any relay to which we can connect and maximum number of hops have not been breached while (hops < maxHops && currentRelayGroup.Any()) { var nextRelayGroup = new List <KeyValuePair <VesselRelayPersistence, int> >(); //will put every relay which is in line of sight of any relay from currentRelayGroup here foreach (var relayEntry in currentRelayGroup) //relays visible from receiver in first iteration, then relays visible from them etc.... { var relay = relayEntry.Key; MicrowaveRoute relayRoute = relayRouteDictionary[relay]; // current best route for this relay double relayRouteFacingFactor = relayRoute.FacingFactor; // it's always facing factor from the beggining of the route for (int t = 0; t < transmittersToCheck.Count; t++) //check if this relay can connect to transmitters { double transmitterDistance = relayToTransmitterDistances[relayEntry.Value, t]; //it's >0 if it can see if (transmitterDistance <= 0) { continue; } double newDistance = relayRoute.Distance + transmitterDistance; // total distance from receiver by this relay to transmitter double efficiencyByThisRelay = ComputeDistanceFacingEfficiency(newDistance, relayRouteFacingFactor); //efficiency MicrowaveRoute currentOptimalRoute; var transmitter = transmittersToCheck[t]; //this will return true if there is already a route to this transmitter if (transmitterRouteDictionary.TryGetValue(transmitter, out currentOptimalRoute)) { if (currentOptimalRoute.Efficiency < efficiencyByThisRelay) { //if route using this relay is better then replace the old route transmitterRouteDictionary[transmitter] = new MicrowaveRoute(efficiencyByThisRelay, newDistance, relayRouteFacingFactor, relay); } } else { //there is no other route to this transmitter yet known so algorithm puts this one as optimal transmitterRouteDictionary[transmitter] = new MicrowaveRoute(efficiencyByThisRelay, newDistance, relayRouteFacingFactor, relay); } } for (int r = 0; r < relaysToCheck.Count; r++) { var nextRelay = relaysToCheck[r]; if (nextRelay == relay) { continue; } double distanceToNextRelay = relayToRelayDistances[relayEntry.Value, r]; if (distanceToNextRelay <= 0) { continue; } double relayToNextRelayDistance = relayRoute.Distance + distanceToNextRelay; double efficiencyByThisRelay = ComputeDistanceFacingEfficiency(relayToNextRelayDistance, relayRouteFacingFactor); MicrowaveRoute currentOptimalPredecessor; if (relayRouteDictionary.TryGetValue(nextRelay, out currentOptimalPredecessor)) //this will return true if there is already a route to next relay { if (currentOptimalPredecessor.Efficiency < efficiencyByThisRelay) { //if route using this relay is better relayRouteDictionary[nextRelay] = new MicrowaveRoute(efficiencyByThisRelay, relayToNextRelayDistance, relayRoute.FacingFactor, relay); } //we put it in dictionary as optimal } else //there is no other route to this relay yet known so we put this one as optimal { relayRouteDictionary[nextRelay] = new MicrowaveRoute(efficiencyByThisRelay, relayToNextRelayDistance, relayRoute.FacingFactor, relay); } if (!coveredRelays.Contains(r)) { nextRelayGroup.Add(new KeyValuePair <VesselRelayPersistence, int>(nextRelay, r)); //in next iteration we will check what next relay can see coveredRelays.Add(r); } } } currentRelayGroup = nextRelayGroup; //we don't have to check old relays so we just replace whole List hops++; } } //building final result var resultDictionary = new Dictionary <VesselMicrowavePersistence, KeyValuePair <double, IEnumerable <VesselRelayPersistence> > >(); foreach (var transmitterEntry in transmitterRouteDictionary) { Stack <VesselRelayPersistence> relays = new Stack <VesselRelayPersistence>();//Last in, first out so relay visible from receiver will always be first VesselRelayPersistence relay = transmitterEntry.Value.PreviousRelay; while (relay != null) { relays.Push(relay); relay = relayRouteDictionary[relay].PreviousRelay; } resultDictionary.Add(transmitterEntry.Key, new KeyValuePair <double, IEnumerable <VesselRelayPersistence> >(transmitterEntry.Value.Efficiency, relays)); } return(resultDictionary); //connectedTransmitters; }
protected double ComputeDistance(Vessel v1, Vessel v2) { return(Vector3d.Distance(PluginHelper.getVesselPos(v1), PluginHelper.getVesselPos(v2))); }
protected double ComputeVisibilityAndDistance(VesselRelayPersistence r, Vessel v) { return(PluginHelper.HasLineOfSightWith(r.getVessel(), v, 0) ? Vector3d.Distance(PluginHelper.getVesselPos(r.getVessel()), PluginHelper.getVesselPos(v)) : -1); }
private void Window(int windowID) { bold_label = new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold }; if (GUI.Button(new Rect(windowPosition.width - 20, 2, 18, 18), "x")) { render_window = false; } GUILayout.BeginVertical(); if (vessel.altitude < PluginHelper.GetMaxAtmosphericAltitude(vessel.mainBody)) { if (analysis_count > analysis_length) { GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#LOC_KSPIE_FNMassSpectrometer_Gas"), bold_label, GUILayout.Width(150)); //"Gas" GUILayout.Label(Localizer.Format("#LOC_KSPIE_MassSpectrometer_Abundance"), bold_label, GUILayout.Width(150)); //"Abundance" GUILayout.EndHorizontal(); GUILayout.Space(5); foreach (var atmospheric_resource in AtmosphericResourceHandler.GetAtmosphericCompositionForBody(vessel.mainBody).Values) { GUILayout.BeginHorizontal(); GUILayout.Label(atmospheric_resource.DisplayName, GUILayout.Width(150)); string resource_abundance_str; if (atmospheric_resource.ResourceAbundance > 0.001) { resource_abundance_str = (atmospheric_resource.ResourceAbundance * 100.0) + "%"; } else { if (atmospheric_resource.ResourceAbundance > 0.000001) { resource_abundance_str = (atmospheric_resource.ResourceAbundance * 1e6) + " ppm"; } else { resource_abundance_str = (atmospheric_resource.ResourceAbundance * 1e9) + " ppb"; } } GUILayout.Label(resource_abundance_str, GUILayout.Width(150)); GUILayout.EndHorizontal(); } } else { double percent_analysed = (double)analysis_count / analysis_length * 100; GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#LOC_KSPIE_MassSpectrometer_Analysing"), GUILayout.Width(150));//"Analysing..." GUILayout.Label(percent_analysed.ToString("0.00") + "%", GUILayout.Width(150)); GUILayout.EndHorizontal(); } } else { GUILayout.Label(Localizer.Format("#LOC_KSPIE_FNLCMassSpectrometer_NoAtomspheretoSample"), GUILayout.ExpandWidth(true));//"--No Atmosphere to Sample--" analysis_count = 0; } GUILayout.EndVertical(); GUI.DragWindow(); }
public override void OnFixedUpdate() { String[] resources_to_supply = { FNResourceManager.FNRESOURCE_MEGAJOULES, FNResourceManager.FNRESOURCE_WASTEHEAT }; this.resources_to_supply = resources_to_supply; base.OnFixedUpdate(); ConfigNode config = PluginHelper.getPluginSaveFile(); float powerInputIncr = 0; float powerInputRelay = 0; int activeSatsIncr = 0; float rangelosses = 0; if (config != null && IsEnabled) { if (getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT) >= 0.95) { IsEnabled = false; deactivate_timer++; if (FlightGlobals.ActiveVessel == vessel && deactivate_timer > 2) { ScreenMessages.PostScreenMessage("Warning Dangerous Overheating Detected: Emergency microwave power shutdown occuring NOW!", 5.0f, ScreenMessageStyle.UPPER_CENTER); } return; } deactivate_timer = 0; //Check to see if active vessel is a relay - for now we do not want a relay to connect to another relay to prevent energy loops String aid = vessel.id.ToString(); if (config.HasValue(aid) == true) { String agenType = config.GetValue(aid + "type"); if (agenType == "relay") { aIsRelay = true; } else { aIsRelay = false; } } //if (activeCount % 100 == 0) { List <Vessel> vessels = FlightGlobals.Vessels; //print(vessels.Count.ToString() + "\n"); //loop through vessels and attempt to add any active sattilites foreach (Vessel vess in vessels) { String vid = vess.id.ToString(); String vname = vess.vesselName.ToString().ToLower(); //print(vid + "\n"); //prevent adding active vessel as sat, skip calculations on debris, only add vessels with config value and line of sight to active vessel if (vess.isActiveVessel == false && vname.IndexOf("debris") == -1 && config.HasValue(vid) == true && lineOfSightTo(vess) == true) { String powerinputsat = config.GetValue(vid); String vgenType = config.GetValue(vid + "type"); // if sat is not relay/nuclear check that it has line of site to sun // NOTE: we need to add a check for relay to check lineOfSiteToSource(vess), and if solar a lineOfSiteFromSourceToSun - to check that the source which it is relaying is still attached to it, and if it is a solar source that it is recieving solar energy if ((vgenType == "solar" && PluginHelper.lineOfSightToSun(vess)) || vgenType == "relay" || vgenType == "nuclear") { float inputPowerFixedAlt = 0; // = float.Parse (powerinputsat) * PluginHelper.getSatFloatCurve ().Evaluate ((float)FlightGlobals.Bodies [0].GetAltitude (vess.transform.position)); float distance = (float)Vector3d.Distance(vessel.transform.position, vess.transform.position); float powerdissip = (float)(Math.Tan(angle) * distance * Math.Tan(angle) * distance); powerdissip = Math.Max(powerdissip / collectorArea, 1); if (vgenType != "relay" && inputPowerFixedAlt > 0) { rangelosses += powerdissip; //Scale energy reception based on angle of reciever to transmitter Vector3d direction_vector = (vess.transform.position - vessel.transform.position).normalized; float facing_factor = Vector3.Dot(part.transform.up, direction_vector); facing_factor = Mathf.Max(0, facing_factor); powerInputIncr += inputPowerFixedAlt / powerdissip * facing_factor; activeSatsIncr++; connectedrelaysf = 0; //print ("warp: sat added - genType: " + vgenType); } // only attach to one relay IF no sattilites are available for direct connection else if (aIsRelay == false && activeSatsIncr < 1 && inputPowerFixedAlt > 0) { rangelosses = powerdissip; //Scale energy reception based on angle of reciever to transmitter Vector3d direction_vector = (vess.transform.position - vessel.transform.position).normalized; float facing_factor = Vector3.Dot(part.transform.up, direction_vector); facing_factor = Mathf.Max(0, facing_factor); powerInputRelay = inputPowerFixedAlt / powerdissip * facing_factor; connectedrelaysf = 1; activeSatsIncr = 0; //print ("warp: relay added"); } } } } float atmosphericefficiency = (float)Math.Exp(-FlightGlobals.getStaticPressure(vessel.transform.position) / 5); if (activeSatsIncr > 0 && powerInputIncr > 0) { this.rangelosses = rangelosses / activeSatsIncr; totefff = efficiency * atmosphericefficiency * 100 / rangelosses; powerInput = powerInputIncr * efficiency * atmosphericefficiency; connectedsatsf = activeSatsIncr; //print ("warp: connected sat"); } else if (connectedrelaysf > 0 && powerInputRelay > 0) { this.rangelosses = rangelosses / connectedrelaysf; totefff = efficiency * atmosphericefficiency * 100 / rangelosses; powerInput = powerInputRelay * efficiency * atmosphericefficiency; connectedsatsf = 0; //print("warp: connected relay"); } else { connectedrelaysf = 0; connectedsatsf = 0; powerInput = 0; //print ("warp: no active sats or relays available"); } //} } else { connectedrelaysf = 0; connectedsatsf = 0; powerInput = 0; } float powerInputMegajoules = powerInput / 1000.0f; supplyFNResource(powerInputMegajoules * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES); float waste_head_production = powerInput / 1000.0f / efficiency * (1.0f - efficiency); supplyFNResource(waste_head_production * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT); //activeCount++; }
public override void OnStart(PartModule.StartState state) { Actions["ToggleToggleResourceAction"].guiName = Events["ToggleResource"].guiName = String.Format("Toggle Resource"); if (state == StartState.Editor) { return; } this.part.force_activate(); // verify if body has atmosphere at all if (!vessel.mainBody.atmosphere) { return; } // verify scoop was enabled if (!scoopIsEnabled) { return; } // verify a timestamp is available if (last_active_time == 0) { return; } // verify any power was avaialble in previous save if (last_power_percentage < 0.01) { return; } // verify altitude is not too high if (vessel.altitude > (PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody) * PluginHelper.MaxAtmosphericAltitudeMult)) { ScreenMessages.PostScreenMessage("Vessel is too high for resource accumulation", 10, ScreenMessageStyle.LOWER_CENTER); return; } // verify altitude is not too low if (vessel.altitude < (PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody))) { ScreenMessages.PostScreenMessage("Vessel is too low for resource accumulation", 10, ScreenMessageStyle.LOWER_CENTER); return; } // verify eccentricity if (vessel.orbit.eccentricity > 0.1) { string message = "Eccentricity of " + vessel.orbit.eccentricity.ToString("0.0000") + " is too High for resource accumulations"; ScreenMessages.PostScreenMessage(message, 10.0f, ScreenMessageStyle.LOWER_CENTER); return; } // verify that an electric or Thermal engine is available with high enough ISP var highIspEngine = part.vessel.parts.Find(p => p.FindModulesImplementing <ElectricEngineControllerFX>().Any(e => e.baseISP > 4200) || p.FindModulesImplementing <ThermalEngineController>().Any(e => e.AttachedReactor.CoreTemperature > 40000)); if (highIspEngine == null) { ScreenMessages.PostScreenMessage("No engine available, with high enough Isp and propelant switch ability to compensate for atmospheric drag", 10, ScreenMessageStyle.LOWER_CENTER); return; } // calcualte time past since last frame double time_diff = (Planetarium.GetUniversalTime() - last_active_time) * 55; // scoop athmosphere for entire durration ScoopAthmosphere(time_diff, true); }
public override void OnUpdate() { base.OnUpdate(); if (!isSwappingFuelMode && (!CheatOptions.InfiniteElectricity && getDemandStableSupply(FNResourceManager.FNRESOURCE_MEGAJOULES) > 1.01) && IsEnabled && !fusion_alert) { fusionAlertFrames++; } else { fusion_alert = false; fusionAlertFrames = 0; } if (fusionAlertFrames > 2) { ScreenMessages.PostScreenMessage("Warning: Fusion Reactor plasma heating cannot be guaranteed, reducing power requirements is recommended.", 0.1f, ScreenMessageStyle.UPPER_CENTER); fusion_alert = true; } electricPowerMaintenance = PluginHelper.getFormattedPowerString(power_consumed) + " / " + PluginHelper.getFormattedPowerString(HeatingPowerRequirements); }
void OnGameStateSaved(Game game) { Debug.Log("[KSPI]: GameEventSubscriber - detected OnGameStateSaved"); PluginHelper.LoadSaveFile(); }
public override void OnStart(PartModule.StartState state) { Actions["DeployRadiatorAction"].guiName = Events["DeployRadiator"].guiName = String.Format("Deploy Radiator"); Actions["RetractRadiatorAction"].guiName = Events["RetractRadiator"].guiName = String.Format("Retract Radiator"); Actions["ToggleRadiatorAction"].guiName = String.Format("Toggle Radiator"); if (state == StartState.Editor) { if (hasTechsRequiredToUpgrade()) { isupgraded = true; hasrequiredupgrade = true; isupgraded = true; } return; } FNRadiator.list_of_radiators.Add(this); anim = part.FindModelAnimators(animName).FirstOrDefault(); //orig_emissive_colour = part.renderer.material.GetTexture (emissive_property_name); if (anim != null) { anim [animName].layer = 1; if (radiatorIsEnabled) { anim.Blend(animName, 1, 0); } else { //anim.Blend (animName, 0, 0); } //anim.Play (); } if (isDeployable) { pivot = part.FindModelTransform("suntransform"); original_eulers = pivot.transform.localEulerAngles; } else { radiatorIsEnabled = true; } if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) { if (PluginHelper.hasTech(upgradeTechReq)) { hasrequiredupgrade = true; } } else { hasrequiredupgrade = true; } if (radiatorInit == false) { radiatorInit = true; } if (!isupgraded) { radiatorType = originalName; } else { radiatorType = upgradedName; radiatorTemp = upgradedRadiatorTemp; } radiatorTempStr = radiatorTemp + "K"; this.part.force_activate(); }
void onGameStateSaved(Game game) { Debug.Log("[KSP Interstellar] GameEventSubscriber - detected onGameStateSaved"); PluginHelper.LoadSaveFile(); }
public override void OnFixedUpdate() { float atmosphere_height = vessel.mainBody.maxAtmosphereAltitude; float vessel_height = (float)vessel.mainBody.GetAltitude(vessel.transform.position); float conv_power_dissip = 0; if (vessel.altitude <= PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody)) { float pressure = (float)FlightGlobals.getStaticPressure(vessel.transform.position); float dynamic_pressure = (float)(0.5 * pressure * 1.2041 * vessel.srf_velocity.sqrMagnitude / 101325.0); pressure += dynamic_pressure; float low_temp = FlightGlobals.getExternalTemperature(vessel.transform.position); float delta_temp = Mathf.Max(0, radiatorTemp - low_temp); conv_power_dissip = pressure * delta_temp * radiatorArea * rad_const_h / 1e6f * TimeWarp.fixedDeltaTime * convectiveBonus; if (!radiatorIsEnabled) { conv_power_dissip = conv_power_dissip / 2.0f; } convectedThermalPower = consumeFNResource(conv_power_dissip, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime; if (radiatorIsEnabled && dynamic_pressure > 1.4854428818159388107574636072046e-3 && isDeployable) { part.deactivate(); //part.breakingForce = 1; //part.breakingTorque = 1; part.decouple(1); } } if (radiatorIsEnabled) { if (getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT) >= 1 && current_rad_temp >= radiatorTemp) { explode_counter++; if (explode_counter > 25) { part.explode(); } } else { explode_counter = 0; } double radiator_temperature_temp_val = radiatorTemp * Math.Pow(getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT), 0.25); if (FNReactor.hasActiveReactors(vessel)) { radiator_temperature_temp_val = Math.Min(FNReactor.getTemperatureofColdestReactor(vessel) / 1.01, radiator_temperature_temp_val); } double thermal_power_dissip = (GameConstants.stefan_const * radiatorArea * Math.Pow(radiator_temperature_temp_val, 4) / 1e6) * TimeWarp.fixedDeltaTime; radiatedThermalPower = consumeFNResource(thermal_power_dissip, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime; double instantaneous_rad_temp = (Math.Min(Math.Pow(radiatedThermalPower * 1e6 / (GameConstants.stefan_const * radiatorArea), 0.25), radiatorTemp)); instantaneous_rad_temp = Math.Max(instantaneous_rad_temp, Math.Max(FlightGlobals.getExternalTemperature((float)vessel.altitude, vessel.mainBody) + 273.16, 2.7)); if (current_rad_temp <= 0) { current_rad_temp = instantaneous_rad_temp; } else { current_rad_temp = instantaneous_rad_temp * alpha + (1.0 - alpha) * instantaneous_rad_temp; } if (isDeployable) { Vector3 pivrot = pivot.rotation.eulerAngles; pivot.Rotate(Vector3.up * 5f * TimeWarp.fixedDeltaTime * directionrotate); Vector3 sunpos = FlightGlobals.Bodies [0].transform.position; Vector3 flatVectorToTarget = sunpos - transform.position; flatVectorToTarget = flatVectorToTarget.normalized; float dot = Mathf.Asin(Vector3.Dot(pivot.transform.right, flatVectorToTarget)) / Mathf.PI * 180.0f; float anglediff = -dot; oldangle = dot; //print (dot); directionrotate = anglediff / 5 / TimeWarp.fixedDeltaTime; directionrotate = Mathf.Min(3, directionrotate); directionrotate = Mathf.Max(-3, directionrotate); part.maximum_drag = 0.8f; part.minimum_drag = 0.8f; } } else { if (isDeployable) { pivot.transform.localEulerAngles = original_eulers; } double radiator_temperature_temp_val = radiatorTemp * Math.Pow(getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT), 0.25); if (FNReactor.hasActiveReactors(vessel)) { radiator_temperature_temp_val = Math.Min(FNReactor.getTemperatureofColdestReactor(vessel) / 1.01, radiator_temperature_temp_val); } double thermal_power_dissip = (GameConstants.stefan_const * radiatorArea * Math.Pow(radiator_temperature_temp_val, 4) / 1e7) * TimeWarp.fixedDeltaTime; radiatedThermalPower = consumeFNResource(thermal_power_dissip, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime; double instantaneous_rad_temp = (Math.Min(Math.Pow(radiatedThermalPower * 1e7 / (GameConstants.stefan_const * radiatorArea), 0.25), radiatorTemp)); instantaneous_rad_temp = Math.Max(instantaneous_rad_temp, Math.Max(FlightGlobals.getExternalTemperature((float)vessel.altitude, vessel.mainBody) + 273.16, 2.7)); if (current_rad_temp <= 0) { current_rad_temp = instantaneous_rad_temp; } else { current_rad_temp = instantaneous_rad_temp * alpha + (1.0 - alpha) * instantaneous_rad_temp; } part.maximum_drag = 0.2f; part.minimum_drag = 0.2f; } }
public static bool HasTechRequirmentOrEmpty(string techName) { return(techName == String.Empty || PluginHelper.upgradeAvailable(techName)); }
public override void OnStart(PartModule.StartState state) { if (state == StartState.Editor) { if (this.HasTechsRequiredToUpgrade()) { isupgraded = true; upgradePartModule(); } return; } if (isupgraded) { upgradePartModule(); } else { if (this.HasTechsRequiredToUpgrade()) { hasrequiredupgrade = true; } } // update gui names Events["BeginResearch"].guiName = beginResearchName; reprocessor = new NuclearFuelReprocessor(part); anti_factory = new AntimatterFactory(part); ConfigNode config = PluginHelper.getPluginSaveFile(); part.force_activate(); anim = part.FindModelAnimators(animName1).FirstOrDefault(); anim2 = part.FindModelAnimators(animName2).FirstOrDefault(); if (anim != null && anim2 != null) { anim[animName1].layer = 1; anim2[animName2].layer = 1; if (IsEnabled) { //anim [animName1].normalizedTime = 1f; //anim2 [animName2].normalizedTime = 1f; //anim [animName1].speed = -1f; //anim2 [animName2].speed = -1f; anim.Blend(animName1, 1, 0); anim2.Blend(animName2, 1, 0); } else { //anim [animName1].normalizedTime = 0f; //anim2 [animName2].normalizedTime = 0f; //anim [animName1].speed = 1f; //anim2 [animName2].speed = 1f; //anim.Blend (animName1, 0, 0);global_rate_multipliers //anim2.Blend (animName2, 0, 0); play_down = false; } //anim.Play (); //anim2.Play (); } if (IsEnabled && last_active_time != 0) { float global_rate_multipliers = 1; crew_capacity_ratio = ((float)part.protoModuleCrew.Count) / ((float)part.CrewCapacity); global_rate_multipliers = global_rate_multipliers * crew_capacity_ratio; if (active_mode == 0) // Science persistence { double time_diff = Planetarium.GetUniversalTime() - last_active_time; float altitude_multiplier = Math.Max((float)(vessel.altitude / (vessel.mainBody.Radius)), 1); float kerbalResearchSkillFactor = part.protoModuleCrew.Sum(proto_crew_member => GetKerbalScienceFactor(proto_crew_member) / 2f); double science_to_increment = kerbalResearchSkillFactor * GameConstants.baseScienceRate * time_diff / GameConstants.EARH_DAY_SECONDS * electrical_power_ratio * global_rate_multipliers * PluginHelper.getScienceMultiplier(vessel) //PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed) / ((float)Math.Sqrt(altitude_multiplier)); science_to_increment = (double.IsNaN(science_to_increment) || double.IsInfinity(science_to_increment)) ? 0 : science_to_increment; science_to_add += (float)science_to_increment; } else if (active_mode == 2) // Antimatter persistence { double time_diff = Planetarium.GetUniversalTime() - last_active_time; List <PartResource> antimatter_resources = part.GetConnectedResources(InterstellarResourcesConfiguration.Instance.Antimatter).ToList(); float currentAntimatter_missing = (float)antimatter_resources.Sum(ar => ar.maxAmount - ar.amount); float total_electrical_power_provided = (float)(electrical_power_ratio * (PluginHelper.BaseAMFPowerConsumption + PluginHelper.BasePowerConsumption) * 1E6); double antimatter_mass = total_electrical_power_provided / GameConstants.warpspeed / GameConstants.warpspeed * 1E6 / 20000.0; float antimatter_peristence_to_add = (float)-Math.Min(currentAntimatter_missing, antimatter_mass * time_diff); part.RequestResource("Antimatter", antimatter_peristence_to_add); } } }
public void UpdateGUI() { if (_bold_label == null) { _bold_label = new GUIStyle(GUI.skin.label); _bold_label.fontStyle = FontStyle.Bold; } GUILayout.BeginHorizontal(); GUILayout.Label("Power", _bold_label, GUILayout.Width(150)); GUILayout.Label(PluginHelper.getFormattedPowerString(CurrentPower) + "/" + PluginHelper.getFormattedPowerString(PowerRequirements), GUILayout.Width(150)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Hydrogen Consumption Rate", _bold_label, GUILayout.Width(150)); GUILayout.Label(_hydrogen_consumption_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Methane Production Rate", _bold_label, GUILayout.Width(150)); GUILayout.Label(_methane_production_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Oxygen Production Rate", _bold_label, GUILayout.Width(150)); GUILayout.Label(_oxygen_production_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150)); GUILayout.EndHorizontal(); }
public override void OnFixedUpdate() { float global_rate_multipliers = 1; crew_capacity_ratio = ((float)part.protoModuleCrew.Count) / ((float)part.CrewCapacity); global_rate_multipliers = global_rate_multipliers * crew_capacity_ratio; if (!IsEnabled) { return; } if (active_mode == 0) // Research { double electrical_power_provided = consumeFNResource(powerReqMult * PluginHelper.BasePowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES); electrical_power_ratio = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BasePowerConsumption / powerReqMult); global_rate_multipliers = global_rate_multipliers * electrical_power_ratio; float kerbalScienceSkillFactor = part.protoModuleCrew.Sum(proto_crew_member => GetKerbalScienceFactor(proto_crew_member) / 2f); float altitude_multiplier = Math.Max((float)(vessel.altitude / (vessel.mainBody.Radius)), 1); science_rate_f = (float)(kerbalScienceSkillFactor * GameConstants.baseScienceRate * PluginHelper.getScienceMultiplier(vessel) //PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed) / GameConstants.EARH_DAY_SECONDS * global_rate_multipliers / (Mathf.Sqrt(altitude_multiplier))); if (ResearchAndDevelopment.Instance != null && !double.IsNaN(science_rate_f) && !double.IsInfinity(science_rate_f)) { //ResearchAndDevelopment.Instance.Science = ResearchAndDevelopment.Instance.Science + science_rate_f * TimeWarp.fixedDeltaTime; science_to_add += science_rate_f * TimeWarp.fixedDeltaTime; } } else if (active_mode == 1) // Fuel Reprocessing { double electrical_power_provided = consumeFNResource(powerReqMult * PluginHelper.BasePowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES); electrical_power_ratio = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BasePowerConsumption / powerReqMult); global_rate_multipliers = global_rate_multipliers * electrical_power_ratio; reprocessor.UpdateFrame(global_rate_multipliers, true); if (reprocessor.getActinidesRemovedPerHour() > 0) { reprocessing_rate_f = (float)(reprocessor.getRemainingAmountToReprocess() / reprocessor.getActinidesRemovedPerHour()); } else { IsEnabled = false; } } else if (active_mode == 2) //Antimatter { double electrical_power_provided = consumeFNResource(powerReqMult * PluginHelper.BaseAMFPowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES); electrical_power_ratio = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BaseAMFPowerConsumption / powerReqMult); global_rate_multipliers = crew_capacity_ratio * electrical_power_ratio; anti_factory.produceAntimatterFrame(global_rate_multipliers); antimatter_rate_f = (float)anti_factory.getAntimatterProductionRate(); } else if (active_mode == 3) { IsEnabled = false; } else if (active_mode == 4) // Centrifuge { if (vessel.Splashed) { float electrical_power_provided = (float)consumeFNResource(powerReqMult * PluginHelper.BaseCentriPowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES); electrical_power_ratio = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BaseCentriPowerConsumption / powerReqMult); global_rate_multipliers = global_rate_multipliers * electrical_power_ratio; float deut_produced = (float)(global_rate_multipliers * GameConstants.deuterium_timescale * GameConstants.deuterium_abudance * 1000.0f); deut_rate_f = -ORSHelper.fixedRequestResource(part, InterstellarResourcesConfiguration.Instance.Deuterium, -deut_produced * TimeWarp.fixedDeltaTime) / TimeWarp.fixedDeltaTime; } else { ScreenMessages.PostScreenMessage("You must be splashed down to perform this activity.", 5.0f, ScreenMessageStyle.UPPER_CENTER); IsEnabled = false; } } if (electrical_power_ratio <= 0) { deut_rate_f = 0; electrolysis_rate_f = 0; science_rate_f = 0; antimatter_rate_f = 0; reprocessing_rate_f = 0; } last_active_time = (float)Planetarium.GetUniversalTime(); }
public override void OnStart(PartModule.StartState state) { var exoticMatterResource = part.Resources.list.FirstOrDefault(r => r.resourceName == InterstellarResourcesConfiguration.Instance.ExoticMatter); // reset Exotic Matter Capacity if (exoticMatterResource != null) { part.mass = partMass; var ratio = Math.Min(1, Math.Max(0, exoticMatterResource.amount / exoticMatterResource.maxAmount)); exoticMatterResource.maxAmount = 0.001; exoticMatterResource.amount = exoticMatterResource.maxAmount * ratio; } InstanceID = GetInstanceID(); if (IsSlave) { UnityEngine.Debug.Log("KSPI - AlcubierreDrive Slave " + InstanceID + " Started"); } else { UnityEngine.Debug.Log("KSPI - AlcubierreDrive Master " + InstanceID + " Started"); } if (!String.IsNullOrEmpty(AnimationName)) { animationState = SetUpAnimation(AnimationName, this.part); } try { Events["StartCharging"].active = !IsSlave; Events["StopCharging"].active = !IsSlave; Events["ActivateWarpDrive"].active = !IsSlave; Events["DeactivateWarpDrive"].active = !IsSlave; Events["ToggleWarpSpeedUp"].active = !IsSlave; Events["ToggleWarpSpeedDown"].active = !IsSlave; Events["ReduceWarpPower"].active = !IsSlave; Fields["exotic_power_required"].guiActive = !IsSlave; Fields["WarpEngineThrottle"].guiActive = !IsSlave; Fields["warpToMassRatio"].guiActive = !IsSlave; Fields["vesselTotalMass"].guiActive = !IsSlave; Fields["DriveStatus"].guiActive = !IsSlave; Fields["minPowerRequirementForLightSpeed"].guiActive = !IsSlave; Fields["currentPowerRequirementForWarp"].guiActive = !IsSlave; Fields["sumOfAlcubierreDrives"].guiActive = !IsSlave; Actions["StartChargingAction"].guiName = Events["StartCharging"].guiName = String.Format("Start Charging"); Actions["StopChargingAction"].guiName = Events["StopCharging"].guiName = String.Format("Stop Charging"); Actions["ToggleChargingAction"].guiName = String.Format("Toggle Charging"); Actions["ActivateWarpDriveAction"].guiName = Events["ActivateWarpDrive"].guiName = String.Format("Activate Warp Drive"); Actions["DeactivateWarpDriveAction"].guiName = Events["DeactivateWarpDrive"].guiName = String.Format("Deactivate Warp Drive"); Actions["ToggleWarpSpeedUpAction"].guiName = Events["ToggleWarpSpeedUp"].guiName = String.Format("Warp Speed (+)"); Actions["ToggleWarpSpeedDownAction"].guiName = Events["ToggleWarpSpeedDown"].guiName = String.Format("Warp Speed (-)"); if (state == StartState.Editor) { return; } if (!IsSlave) { UnityEngine.Debug.Log("KSPI - AlcubierreDrive Create Slaves"); alcubierreDrives = part.vessel.FindPartModulesImplementing <AlcubierreDrive>(); foreach (var drive in alcubierreDrives) { var driveId = drive.GetInstanceID(); if (driveId != InstanceID) { drive.IsSlave = true; UnityEngine.Debug.Log("KSPI - AlcubierreDrive " + driveId + " != " + InstanceID); } } } UnityEngine.Debug.Log("KSPI - AlcubierreDrive OnStart step C "); this.part.force_activate(); if (serialisedwarpvector != null) { heading_act = ConfigNode.ParseVector3D(serialisedwarpvector); } warp_effect = GameObject.CreatePrimitive(PrimitiveType.Cylinder); warp_effect2 = GameObject.CreatePrimitive(PrimitiveType.Cylinder); warp_effect.collider.enabled = false; warp_effect2.collider.enabled = false; Vector3 ship_pos = new Vector3(part.transform.position.x, part.transform.position.y, part.transform.position.z); Vector3 end_beam_pos = ship_pos + transform.up * warp_size; Vector3 mid_pos = (ship_pos - end_beam_pos) / 2.0f; warp_effect.transform.localScale = new Vector3(effectSize1, mid_pos.magnitude, effectSize1); warp_effect.transform.position = new Vector3(mid_pos.x, ship_pos.y + mid_pos.y, mid_pos.z); warp_effect.transform.rotation = part.transform.rotation; warp_effect2.transform.localScale = new Vector3(effectSize2, mid_pos.magnitude, effectSize2); warp_effect2.transform.position = new Vector3(mid_pos.x, ship_pos.y + mid_pos.y, mid_pos.z); warp_effect2.transform.rotation = part.transform.rotation; //warp_effect.layer = LayerMask.NameToLayer("Ignore Raycast"); //warp_effect.renderer.material = new Material(KSP.IO.File.ReadAllText<AlcubierreDrive>("AlphaSelfIllum.shader")); warp_effect.renderer.material.shader = Shader.Find("Unlit/Transparent"); warp_effect2.renderer.material.shader = Shader.Find("Unlit/Transparent"); warp_textures = new Texture[33]; const string warp_tecture_path = "WarpPlugin/ParticleFX/warp"; for (int i = 0; i < 11; i++) { warp_textures[i] = GameDatabase.Instance.GetTexture((i > 0) ? warp_tecture_path + (i + 1).ToString() : warp_tecture_path, false); } warp_textures[11] = GameDatabase.Instance.GetTexture("WarpPlugin/ParticleFX/warp10", false); for (int i = 12; i < 33; i++) { int j = i > 17 ? 34 - i : i; warp_textures[i] = GameDatabase.Instance.GetTexture(j > 1 ? warp_tecture_path + (j + 1).ToString() : warp_tecture_path, false); } warp_textures2 = new Texture[33]; const string warpr_tecture_path = "WarpPlugin/ParticleFX/warpr"; for (int i = 0; i < 11; i++) { warp_textures2[i] = GameDatabase.Instance.GetTexture((i > 0) ? warpr_tecture_path + (i + 1).ToString() : warpr_tecture_path, false); } warp_textures2[11] = GameDatabase.Instance.GetTexture("WarpPlugin/ParticleFX/warpr10", false); for (int i = 12; i < 33; i++) { int j = i > 17 ? 34 - i : i; warp_textures2[i] = GameDatabase.Instance.GetTexture(j > 1 ? warpr_tecture_path + (j + 1).ToString() : warpr_tecture_path, false); } warp_effect.renderer.material.color = new Color(Color.cyan.r, Color.cyan.g, Color.cyan.b, 0.5f); warp_effect2.renderer.material.color = new Color(Color.red.r, Color.red.g, Color.red.b, 0.1f); warp_effect.renderer.material.mainTexture = warp_textures[0]; warp_effect.renderer.receiveShadows = false; //warp_effect.layer = LayerMask.NameToLayer ("Ignore Raycast"); //warp_effect.collider.isTrigger = true; warp_effect2.renderer.material.mainTexture = warp_textures2[0]; warp_effect2.renderer.receiveShadows = false; warp_effect2.renderer.material.mainTextureOffset = new Vector2(-0.2f, -0.2f); //warp_effect2.layer = LayerMask.NameToLayer ("Ignore Raycast"); //warp_effect2.collider.isTrigger = true; warp_effect2.renderer.material.renderQueue = 1000; warp_effect.renderer.material.renderQueue = 1001; /*gameObject.AddComponent<Light>(); * gameObject.light.color = Color.cyan; * gameObject.light.intensity = 1f; * gameObject.light.range = 4000f; * gameObject.light.type = LightType.Spot; * gameObject.light.transform.position = end_beam_pos; * gameObject.light.cullingMask = ~0;*/ //light. warp_sound = gameObject.AddComponent <AudioSource>(); warp_sound.clip = GameDatabase.Instance.GetAudioClip("WarpPlugin/Sounds/warp_sound"); warp_sound.volume = GameSettings.SHIP_VOLUME; warp_sound.panLevel = 0; warp_sound.rolloffMode = AudioRolloffMode.Linear; warp_sound.Stop(); if (IsEnabled) { warp_sound.Play(); warp_sound.loop = true; } bool manual_upgrade = false; if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) { if (upgradeTechReq != null) { if (PluginHelper.hasTech(upgradeTechReq)) { hasrequiredupgrade = true; } else if (upgradeTechReq == "none") { manual_upgrade = true; } } else { manual_upgrade = true; } } else { hasrequiredupgrade = true; } if (warpInit == false) { warpInit = true; if (hasrequiredupgrade) { isupgraded = true; } } if (manual_upgrade) { hasrequiredupgrade = true; } if (isupgraded) { warpdriveType = upgradedName; } else { warpdriveType = originalName; } //warp_effect.transform.localScale.y = 2.5f; //warp_effect.transform.localScale.z = 200f; // disable charging at startup IsCharging = false; } catch (Exception e) { UnityEngine.Debug.LogError("KSPI - AlcubierreDrive OnStart 1 Exception " + e.Message); } try { warpdriveType = originalName; minimum_selected_factor = engine_throtle.ToList().IndexOf(engine_throtle.First(w => w == 1f)); if (selected_factor == -1) { selected_factor = minimum_selected_factor; } } catch (Exception e) { UnityEngine.Debug.LogError("KSPI - AlcubierreDrive OnStart 2 Exception " + e.Message); } }
public InterstellarResourcesConfiguration(ConfigNode plugin_settings) { if (plugin_settings != null) { if (plugin_settings.HasValue("AluminiumResourceName")) { _aluminium = plugin_settings.GetValue("AluminiumResourceName"); Debug.Log("[KSP Interstellar] Aluminium resource name set to " + Aluminium); } if (plugin_settings.HasValue("AmmoniaResourceName")) { _ammonia = plugin_settings.GetValue("AmmoniaResourceName"); Debug.Log("[KSP Interstellar] Ammonia resource name set to " + Ammonia); } if (plugin_settings.HasValue("ArgonResourceName")) { _argon = plugin_settings.GetValue("ArgonResourceName"); Debug.Log("[KSP Interstellar] Argon resource name set to " + Argon); } if (plugin_settings.HasValue("CarbonDioxideResourceName")) { _carbonDioxide = plugin_settings.GetValue("CarbonDioxideResourceName"); Debug.Log("[KSP Interstellar] CarbonDioxide resource name set to " + CarbonDioxide); } if (plugin_settings.HasValue("CarbonMonoxideResourceName")) { _carbonMoxoxide = plugin_settings.GetValue("CarbonMonoxideResourceName"); Debug.Log("[KSP Interstellar] CarbonMonoxide resource name set to " + CarbonMoxoxide); } if (plugin_settings.HasValue("HeliumResourceName")) { _helium4 = plugin_settings.GetValue("HeliumResourceName"); Debug.Log("[KSP Interstellar] Helium4 resource name set to " + Helium); } if (plugin_settings.HasValue("Helium3ResourceName")) { _helium3 = plugin_settings.GetValue("Helium3ResourceName"); Debug.Log("[KSP Interstellar] Helium3 resource name set to " + Helium3); } if (plugin_settings.HasValue("HydrazineResourceName")) { _hydrazine = plugin_settings.GetValue("HydrazineResourceName"); Debug.Log("[KSP Interstellar] Hydrazine resource name set to " + Hydrazine); } if (plugin_settings.HasValue("HydrogenResourceName")) { _hydrogen = plugin_settings.GetValue("HydrogenResourceName"); Debug.Log("[KSP Interstellar] Hydrogen resource name set to " + Hydrogen); } if (plugin_settings.HasValue("HydrogenPeroxideResourceName")) { _hydrogen_peroxide = plugin_settings.GetValue("HydrogenPeroxideResourceName"); Debug.Log("[KSP Interstellar] Hydrogen Peroxide resource name set to " + HydrogenPeroxide); } if (plugin_settings.HasValue("MethaneResourceName")) { _methane = plugin_settings.GetValue("MethaneResourceName"); Debug.Log("[KSP Interstellar] Methane resource name set to " + Methane); } if (plugin_settings.HasValue("NitrogenResourceName")) { _nitrogen = plugin_settings.GetValue("NitrogenResourceName"); Debug.Log("[KSP Interstellar] Nitrogen resource name set to " + Nitrogen); } if (plugin_settings.HasValue("OxygenResourceName")) { _oxygen = plugin_settings.GetValue("OxygenResourceName"); Debug.Log("[KSP Interstellar] Oxygen resource name set to " + Oxygen); } if (plugin_settings.HasValue("TritiumResourceName")) { _tritium = plugin_settings.GetValue("TritiumResourceName"); Debug.Log("[KSP Interstellar] Tritium resource name set to " + _tritium); } if (plugin_settings.HasValue("UraniumTetraflourideName")) { _uranium_TerraFloride = plugin_settings.GetValue("UraniumTetraflourideName"); Debug.Log("[KSP Interstellar] UraniumTetraflouride resource name set to " + _uranium_TerraFloride); } if (plugin_settings.HasValue("WaterResourceName")) { _water = plugin_settings.GetValue("WaterResourceName"); Debug.Log("[KSP Interstellar] Water resource name set to " + Water); } } else { PluginHelper.showInstallationErrorMessage(); } }
public void UpdateGUI() { if (_bold_label == null) { _bold_label = new GUIStyle(GUI.skin.label); _bold_label.fontStyle = FontStyle.Bold; } GUILayout.BeginHorizontal(); GUILayout.Label("Power", _bold_label, GUILayout.Width(150)); GUILayout.Label(PluginHelper.getFormattedPowerString(CurrentPower) + "/" + PluginHelper.getFormattedPowerString(PowerRequirements), GUILayout.Width(150)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Ammona Consumption Rate", _bold_label, GUILayout.Width(150)); GUILayout.Label(_ammonia_consumption_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Uranium Tetraflouride Consumption Rate", _bold_label, GUILayout.Width(150)); GUILayout.Label(_uranium_tetraflouride_consumption_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Uranium Nitride Production Rate", _bold_label, GUILayout.Width(150)); GUILayout.Label(_uranium_nitride_production_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150)); GUILayout.EndHorizontal(); }
public void update(long counter) { var timeWarpFixedDeltaTime = TimeWarpFixedDeltaTime; IsUpdatedAtLeastOnce = true; Counter = counter; stored_supply = currentPowerSupply; stored_stable_supply = stable_supply; stored_resource_demand = current_resource_demand; stored_current_demand = current_resource_demand; stored_current_hp_demand = high_priority_resource_demand; stored_current_charge_demand = charge_resource_demand; stored_charge_demand = charge_resource_demand; stored_total_power_supplied = total_power_distributed; current_resource_demand = 0; high_priority_resource_demand = 0; charge_resource_demand = 0; total_power_distributed = 0; double availableResourceAmount; double maxResouceAmount; my_part.GetConnectedResourceTotals(resourceDefinition.id, out availableResourceAmount, out maxResouceAmount); if (maxResouceAmount > 0 && !double.IsNaN(maxResouceAmount) && !double.IsNaN(availableResourceAmount)) { resource_bar_ratio_end = availableResourceAmount / maxResouceAmount; } else { resource_bar_ratio_end = 0.0001; } double missingResourceAmount = maxResouceAmount - availableResourceAmount; currentPowerSupply += availableResourceAmount; double high_priority_demand_supply_ratio = high_priority_resource_demand > 0 ? Math.Min((currentPowerSupply - stored_current_charge_demand) / stored_current_hp_demand, 1.0) : 1.0; double demand_supply_ratio = stored_current_demand > 0 ? Math.Min((currentPowerSupply - stored_current_charge_demand - stored_current_hp_demand) / stored_current_demand, 1.0) : 1.0; //Prioritise supplying stock ElectricCharge resource if (resourceDefinition.id == megajouleResourceDefinition.id && stored_stable_supply > 0) { double amount; double maxAmount; my_part.GetConnectedResourceTotals(electricResourceDefinition.id, out amount, out maxAmount); double stock_electric_charge_needed = maxAmount - amount; double power_supplied = Math.Min(currentPowerSupply * 1000 * timeWarpFixedDeltaTime, stock_electric_charge_needed); if (stock_electric_charge_needed > 0) { var deltaResourceDemand = stock_electric_charge_needed / 1000 / timeWarpFixedDeltaTime; current_resource_demand += deltaResourceDemand; charge_resource_demand += deltaResourceDemand; } if (power_supplied > 0) { double fixed_provided_electric_charge_in_MW = my_part.RequestResource(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, -power_supplied) / 1000; var provided_electric_charge_per_second = fixed_provided_electric_charge_in_MW / timeWarpFixedDeltaTime; total_power_distributed += -provided_electric_charge_per_second; currentPowerSupply += provided_electric_charge_per_second; } } power_supply_list_archive = power_produced.OrderByDescending(m => m.Value.maximumSupply).ToList(); // store current supply and update average power_supply_list_archive.ForEach(m => { Queue <double> queue; if (!power_produced_history.TryGetValue(m.Key, out queue)) { queue = new Queue <double>(10); power_produced_history.Add(m.Key, queue); } if (queue.Count > 10) { queue.Dequeue(); } queue.Enqueue(m.Value.currentSupply); m.Value.averageSupply = queue.Average(); }); List <KeyValuePair <IResourceSuppliable, PowerDistribution> > power_draw_items = power_consumption.OrderBy(m => m.Value.Power_draw).ToList(); power_draw_list_archive = power_draw_items.ToList(); power_draw_list_archive.Reverse(); // check priority 1 parts like reactors foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items) { IResourceSuppliable resourceSuppliable = power_kvp.Key; if (resourceSuppliable.getPowerPriority() == 1) { double power = power_kvp.Value.Power_draw; current_resource_demand += power; high_priority_resource_demand += power; if (flow_type == FNRESOURCE_FLOWTYPE_EVEN) { power = power * high_priority_demand_supply_ratio; } double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0); currentPowerSupply -= power_supplied; total_power_distributed += power_supplied; //notify of supply resourceSuppliable.receiveFNResource(power_supplied, this.resource_name); } } // check priority 2 parts like reactors foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items) { IResourceSuppliable resourceSuppliable = power_kvp.Key; if (resourceSuppliable.getPowerPriority() == 2) { double power = power_kvp.Value.Power_draw; current_resource_demand += power; if (flow_type == FNRESOURCE_FLOWTYPE_EVEN) { power = power * demand_supply_ratio; } double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0); currentPowerSupply -= power_supplied; total_power_distributed += power_supplied; //notify of supply resourceSuppliable.receiveFNResource(power_supplied, this.resource_name); } } // check priority 3 parts like engines and nuclear reactors foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items) { IResourceSuppliable resourceSuppliable = power_kvp.Key; if (resourceSuppliable.getPowerPriority() == 3) { double power = power_kvp.Value.Power_draw; current_resource_demand += power; if (flow_type == FNRESOURCE_FLOWTYPE_EVEN) { power = power * demand_supply_ratio; } double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0); currentPowerSupply -= power_supplied; total_power_distributed += power_supplied; //notify of supply resourceSuppliable.receiveFNResource(power_supplied, this.resource_name); } } // check priority 4 parts like antimatter reactors, engines and transmitters foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items) { IResourceSuppliable resourceSuppliable = power_kvp.Key; if (resourceSuppliable.getPowerPriority() == 4) { double power = power_kvp.Value.Power_draw; current_resource_demand += power; if (flow_type == FNRESOURCE_FLOWTYPE_EVEN) { power = power * demand_supply_ratio; } double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0); currentPowerSupply -= power_supplied; total_power_distributed += power_supplied; //notify of supply resourceSuppliable.receiveFNResource(power_supplied, this.resource_name); } } // check priority 5 parts and higher foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items) { IResourceSuppliable resourceSuppliable = power_kvp.Key; if (resourceSuppliable.getPowerPriority() >= 5) { double power = power_kvp.Value.Power_draw; current_resource_demand += power; if (flow_type == FNRESOURCE_FLOWTYPE_EVEN) { power = power * demand_supply_ratio; } double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0); currentPowerSupply -= power_supplied; total_power_distributed += power_supplied; //notify of supply resourceSuppliable.receiveFNResource(power_supplied, this.resource_name); } } // substract avaialble resource amount to get delta resource change currentPowerSupply -= Math.Max(availableResourceAmount, 0.0); internl_power_extract_fixed = -currentPowerSupply * timeWarpFixedDeltaTime; if (resourceDefinition.id == wasteheatResourceDefinition.id) { // passive dissip of waste heat - a little bit of this double vessel_mass = my_vessel.GetTotalMass(); double passive_dissip = 2947.295521 * GameConstants.stefan_const * vessel_mass * 2; internl_power_extract_fixed += passive_dissip * TimeWarp.fixedDeltaTime; if (my_vessel.altitude <= PluginHelper.getMaxAtmosphericAltitude(my_vessel.mainBody)) { // passive convection - a lot of this double pressure = FlightGlobals.getStaticPressure(my_vessel.transform.position) * 0.01; double conv_power_dissip = pressure * 40 * vessel_mass * GameConstants.rad_const_h / 1e6 * TimeWarp.fixedDeltaTime; internl_power_extract_fixed += conv_power_dissip; } } if (internl_power_extract_fixed > 0) { internl_power_extract_fixed = Math.Min(internl_power_extract_fixed, availableResourceAmount); } else { internl_power_extract_fixed = Math.Max(internl_power_extract_fixed, -missingResourceAmount); } my_part.RequestResource(resourceDefinition.id, internl_power_extract_fixed); my_part.GetConnectedResourceTotals(resourceDefinition.id, out availableResourceAmount, out maxResouceAmount); if (maxResouceAmount > 0 && !double.IsNaN(maxResouceAmount) && !double.IsNaN(availableResourceAmount)) { resource_bar_ratio_begin = availableResourceAmount / maxResouceAmount; } else { resource_bar_ratio_begin = resourceDefinition.id == wasteheatResourceDefinition.id ? 0.999 : 0; } //calculate total input and output //var total_current_supplied = power_produced.Sum(m => m.Value.currentSupply); //var total_current_provided = power_produced.Sum(m => m.Value.currentProvided); //var total_power_consumed = power_consumption.Sum(m => m.Value.Power_consume); //var total_power_min_supplied = power_produced.Sum(m => m.Value.minimumSupply); ////generate wasteheat from used thermal power + thermal store //if (!CheatOptions.IgnoreMaxTemperature && total_current_produced > 0 && // (resourceDefinition.id == thermalpowerResourceDefinition.id || resourceDefinition.id == chargedpowerResourceDefinition.id)) //{ // var min_supplied_fixed = TimeWarp.fixedDeltaTime * total_power_min_supplied; // var used_or_stored_power_fixed = TimeWarp.fixedDeltaTime * Math.Min(total_power_consumed, total_current_produced) + Math.Max(-actual_stored_power, 0); // var wasteheat_produced_fixed = Math.Max(min_supplied_fixed, used_or_stored_power_fixed); // var effective_wasteheat_ratio = Math.Max(wasteheat_produced_fixed / (total_current_produced * TimeWarp.fixedDeltaTime), 1); // ORSResourceManager manager = ORSResourceOvermanager.getResourceOvermanagerForResource(ResourceManager.FNRESOURCE_WASTEHEAT).getManagerForVessel(my_vessel); // foreach (var supplier_key_value in power_produced) // { // if (supplier_key_value.Value.currentSupply > 0) // { // manager.powerSupplyPerSecondWithMax(supplier_key_value.Key, supplier_key_value.Value.currentSupply * effective_wasteheat_ratio, supplier_key_value.Value.maximumSupply * effective_wasteheat_ratio); // } // } //} currentPowerSupply = 0; stable_supply = 0; power_produced.Clear(); power_consumption.Clear(); }