protected void saveState() { if (HighLogic.LoadedSceneIsFlight) { ConfigNode config = PluginHelper.getPluginSaveFile(); string vesselID = vessel.id.ToString(); if (config.HasNode("VESSEL_SEISMIC_PROBE_" + vesselID)) { ConfigNode probe_node = config.GetNode("VESSEL_SEISMIC_PROBE_" + vesselID); if (probe_node.HasValue("is_active")) { probe_node.SetValue("is_active", probeIsEnabled.ToString()); } else { probe_node.AddValue("is_active", probeIsEnabled.ToString()); } if (probe_node.HasValue("celestial_body")) { probe_node.SetValue("celestial_body", vessel.mainBody.flightGlobalsIndex.ToString()); } else { probe_node.AddValue("celestial_body", vessel.mainBody.flightGlobalsIndex.ToString()); } } else { ConfigNode probe_node = config.AddNode("VESSEL_SEISMIC_PROBE_" + vesselID); probe_node.AddValue("is_active", probeIsEnabled.ToString()); probe_node.AddValue("celestial_body", vessel.mainBody.flightGlobalsIndex.ToString()); } config.Save(PluginHelper.getPluginSaveFilePath()); } }
protected override void cleanUpScienceData() { if (science_vess_ref != null) { ConfigNode config = PluginHelper.getPluginSaveFile(); if (config.HasNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper())) { ConfigNode planet_data = config.GetNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper()); if (planet_data.HasNode(science_vess_ref)) { ConfigNode impact_node = planet_data.GetNode(science_vess_ref); if (impact_node.HasValue("transmitted")) { impact_node.SetValue("transmitted", "True"); } config.Save(PluginHelper.getPluginSaveFilePath()); } } } }
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 distribution_factor = 0; 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("distribution_factor")) { distribution_factor = float.Parse(probe_data.GetValue("distribution_factor")); } if (!transmitted) { ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.SrfLanded, vessel.mainBody, vessel.mainBody.name + "'s surface."); if (subject == null) { return(false); } subject.subjectValue = PluginHelper.getScienceMultiplier(vessel); subject.scienceCap = 10 * experiment.baseValue * subject.subjectValue; float base_science = experiment.baseValue * distribution_factor; data_size = base_science * subject.dataScale; science_data = new ScienceData((float)data_size, 1f, 0f, subject.id, "Impactor Data"); 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."; float science_amount = base_science * subject.subjectValue; recovery_value = science_amount * subject.scientificValue; transmit_value = recovery_value; ref_value = subject.scienceCap; return(true); } } } } return(false); }
public override void OnStart(PartModule.StartState state) { if (state == StartState.Editor) { return; } reprocessor = new FuelReprocessor(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); //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 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); float stupidity = 0; foreach (ProtoCrewMember proto_crew_member in part.protoModuleCrew) { stupidity += proto_crew_member.stupidity; } stupidity = 1.5f - stupidity / 2.0f; double science_to_add = GameConstants.baseScienceRate * time_diff / 86400 * electrical_power_ratio * stupidity * global_rate_multipliers * PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed) / ((float)Math.Sqrt(altitude_multiplier)); //part.RequestResource ("Science", -science_to_add); science_awaiting_addition = science_to_add; } else if (active_mode == 2) // Antimatter persistence { double now = Planetarium.GetUniversalTime(); double time_diff = now - last_active_time; List <PartResource> partresources = new List <PartResource>(); part.GetConnectedResources(PartResourceLibrary.Instance.GetDefinition("Antimatter").id, partresources); float currentAntimatter_missing = 0; foreach (PartResource partresource in partresources) { currentAntimatter_missing += (float)(partresource.maxAmount - partresource.amount); } float total_electrical_power_provided = (float)(electrical_power_ratio * (GameConstants.baseAMFPowerConsumption + GameConstants.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 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 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 net_science = 0; double initial_science = 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; net_science = 50 * PluginHelper.getScienceMultiplier(vessel); //PluginHelper.getImpactorScienceMultiplier(body); initial_science = net_science; } else { net_science += (1.0 - Vector3d.Dot(surface_vector, net_vector.normalized)) * 50 * PluginHelper.getScienceMultiplier(vessel); //PluginHelper.getImpactorScienceMultiplier(body); net_vector = net_vector + surface_vector; } } } net_science = Math.Min(net_science, initial_science * 3.5); // no more than 3.5x boost to science by using multiple detectors if (net_science > 0 && !double.IsInfinity(net_science) && !double.IsNaN(net_science)) { double science_coeff = -science_experiment_number / 2.0; net_science = net_science * Math.Exp(science_coeff); 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("science"), net_science); impact_node.AddValue(string.Intern("number"), (science_experiment_number + 1).ToString("0")); science_node.AddNode(impact_node); config.Save(PluginHelper.PluginSaveFilePath); } }
public override void OnFixedUpdate() { activeCount++; if (IsEnabled) { List <Part> vesselparts = vessel.parts; float electrical_current_available = 0; for (int i = 0; i < vesselparts.Count; ++i) { Part cPart = vesselparts.ElementAt(i); PartModuleList pml = cPart.Modules; for (int j = 0; j < pml.Count; ++j) { var curFNGen = pml.GetModule(j) as FNGenerator; var curMwRec = pml.GetModule(j) as MicrowavePowerReceiver; var curSolarPan = pml.GetModule(j) as ModuleDeployableSolarPanel; if (curFNGen != null) { float consumeMJ = curFNGen.getMaxPowerOutput() * TimeWarp.fixedDeltaTime; float cvalue = consumeFNResource(consumeMJ, FNResourceManager.FNRESOURCE_MEGAJOULES); electrical_current_available = cvalue * 1000 / TimeWarp.fixedDeltaTime; nuclear = true; } else if (curMwRec != null && nuclear == false) { //electrical_current_available = curMwRec.powerInput; part.RequestResource("ElectricCharge", electrical_current_available * TimeWarp.fixedDeltaTime); microwave = true; } else if (curSolarPan != null && nuclear == false && microwave == false) { electrical_current_available += curSolarPan.flowRate; part.RequestResource("ElectricCharge", electrical_current_available * TimeWarp.fixedDeltaTime); solar = true; } } } inputPower = electrical_current_available; } else { inputPower = 0; } if (activeCount % 1000 == 9) { ConfigNode config = PluginHelper.getPluginSaveFile(); string genType = "undefined"; //float inputPowerFixedAlt = (float) ((double)inputPower * (Math.Pow(FlightGlobals.Bodies[0].GetAltitude(vessel.transform.position), 2)) / PluginHelper.FIXED_SAT_ALTITUDE / PluginHelper.FIXED_SAT_ALTITUDE); float inputPowerFixedAlt = 0; if (nuclear == true) { inputPowerFixedAlt = inputPower; //print ("warp: nuclear inputPower " + inputPowerFixedAlt); genType = "nuclear"; } else if (microwave == true) { inputPowerFixedAlt = inputPower; //print ("warp: relay inputPower " + inputPowerFixedAlt); genType = "relay"; } else if (solar == true) { //inputPowerFixedAlt = inputPower / PluginHelper.getSatFloatCurve ().Evaluate ((float)FlightGlobals.Bodies [0].GetAltitude (vessel.transform.position)); //print ("warp: solar inputPower " + inputPowerFixedAlt); genType = "solar"; } if (genType != "undefined") { string vesselIDSolar = vessel.id.ToString(); string outputPower = inputPowerFixedAlt.ToString("0.000"); if (!config.HasValue(vesselIDSolar)) { config.AddValue(vesselIDSolar, outputPower); } else { config.SetValue(vesselIDSolar, outputPower); } if (!config.HasValue(vesselIDSolar + "type")) { config.AddValue(vesselIDSolar + "type", genType); } else { config.SetValue(vesselIDSolar + "type", genType); } config.Save(PluginHelper.getPluginSaveFilePath()); } } }
public void onVesselAboutToBeDestroyed() { print("[KSP Interstellar] Handling Impactor"); int body = vessel.mainBody.flightGlobalsIndex; //print(vessel.srf_velocity.magnitude); ConfigNode config = PluginHelper.getPluginSaveFile(); Vector3d net_vector = Vector3d.zero; bool first = true; double net_science = 0; double initial_science = 0; foreach (Vessel conf_vess in FlightGlobals.Vessels) { String conf_vess_ID = conf_vess.id.ToString(); if (config.HasNode("VESSEL_SEISMIC_PROBE_" + conf_vess_ID)) { ConfigNode probe_node = config.GetNode("VESSEL_SEISMIC_PROBE_" + conf_vess_ID); bool is_active = false; int planet = 0; if (probe_node.HasValue("is_active")) { is_active = bool.Parse(probe_node.GetValue("is_active")); } if (probe_node.HasValue("celestial_body")) { planet = int.Parse(probe_node.GetValue("celestial_body")); } double theta = vessel.longitude; double phi = vessel.latitude; Vector3d up = vessel.mainBody.GetSurfaceNVector(phi, theta).normalized; double surface_height = vessel.mainBody.pqsController.GetSurfaceHeight(QuaternionD.AngleAxis(theta, Vector3d.down) * QuaternionD.AngleAxis(phi, Vector3d.forward) * Vector3d.right) - vessel.mainBody.Radius; double height_diff = vessel.pqsAltitude - surface_height; // record science if we have crashed into the surface at velocity > 40m/s if (is_active && planet == body && vessel.heightFromSurface <= 0.75 && vessel.srf_velocity.magnitude > 40 && height_diff <= 1) { // 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; net_science = 50 * PluginHelper.getImpactorScienceMultiplier(body); initial_science = net_science; } else { net_science += (1.0 - Vector3d.Dot(surface_vector, net_vector.normalized)) * 50 * PluginHelper.getImpactorScienceMultiplier(body); net_vector = net_vector + surface_vector; } } else { if (vessel.heightFromSurface > 0.5) { print("[KSP Interstellar] Impactor: Ignored due to vessel being destroyed at too high altitude."); } if (vessel.srf_velocity.magnitude <= 40) { print("[KSP Interstellar] Impactor: Ignored due to vessel being at too low velocity."); } } } } net_science = Math.Min(net_science, initial_science * 3.5); // no more than 3.5x boost to science by using multiple detectors if (net_science > 0 && !double.IsInfinity(net_science) && !double.IsNaN(net_science)) { ConfigNode science_node; int science_experiment_number = 0; if (config.HasNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper())) { science_node = config.GetNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper()); science_experiment_number = science_node.nodes.Count; } else { science_node = config.AddNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper()); science_node.AddValue("name", "interstellarseismicarchive"); } double science_coeff = -science_experiment_number / 2.0; net_science = net_science * Math.Exp(science_coeff); ScreenMessages.PostScreenMessage("Impact Recorded, science report can now be accessed from one of your accelerometers deployed on this body.", 5f, ScreenMessageStyle.UPPER_CENTER); //science_node.AddValue(vessel.id.ToString(), net_science); if (!science_node.HasNode("IMPACT_" + vessel.id.ToString())) { ConfigNode impact_node = new ConfigNode("IMPACT_" + vessel.id.ToString()); impact_node.AddValue("transmitted", "False"); impact_node.AddValue("vesselname", vessel.vesselName); impact_node.AddValue("science", net_science); impact_node.AddValue("number", (science_experiment_number + 1).ToString("0")); science_node.AddNode(impact_node); } //if (ResearchAndDevelopment.Instance != null) { // ResearchAndDevelopment.Instance.Science = ResearchAndDevelopment.Instance.Science + (float)net_science; //} config.Save(PluginHelper.getPluginSaveFilePath()); } }
public override void OnFixedUpdate() { activeCount++; nuclear_power = 0; solar_power = 0; displayed_solar_power = 0; if (IsEnabled && !relay) { foreach (FNGenerator generator in generators) { if (generator.isActive()) { IThermalSource thermal_source = generator.getThermalSource(); if (thermal_source != null && !thermal_source.IsVolatileSource) { double output = generator.getMaxPowerOutput(); if (thermal_source is InterstellarFusionReactor) { output = output * 0.95; } output = output * transmitPower / 100.0; double gpower = consumeFNResource(output * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES); nuclear_power += gpower * 1000 / TimeWarp.fixedDeltaTime; } } } foreach (ModuleDeployableSolarPanel panel in panels) { double output = panel.flowRate; double spower = part.RequestResource("ElectricCharge", output * TimeWarp.fixedDeltaTime); double inv_square_mult = Math.Pow(Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2) / Math.Pow(Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2); displayed_solar_power += spower / TimeWarp.fixedDeltaTime; //scale solar power to what it would be in Kerbin orbit for file storage solar_power += spower / TimeWarp.fixedDeltaTime / inv_square_mult; } } if (double.IsInfinity(nuclear_power) || double.IsNaN(nuclear_power)) { nuclear_power = 0; } if (double.IsInfinity(solar_power) || double.IsNaN(solar_power)) { solar_power = 0; } if (activeCount % 1000 == 9) { ConfigNode config = PluginHelper.getPluginSaveFile(); string vesselID = vessel.id.ToString(); if (config.HasNode("VESSEL_MICROWAVE_POWER_" + vesselID)) { ConfigNode power_node = config.GetNode("VESSEL_MICROWAVE_POWER_" + vesselID); if (power_node.HasValue("nuclear_power")) { power_node.SetValue("nuclear_power", MicrowavePowerTransmitter.getEnumeratedNuclearPowerForVessel(vessel).ToString("E")); } else { power_node.AddValue("nuclear_power", MicrowavePowerTransmitter.getEnumeratedNuclearPowerForVessel(vessel).ToString("E")); } if (power_node.HasValue("solar_power")) { power_node.SetValue("solar_power", MicrowavePowerTransmitter.getEnumeratedSolarPowerForVessel(vessel).ToString("E")); } else { power_node.AddValue("solar_power", MicrowavePowerTransmitter.getEnumeratedSolarPowerForVessel(vessel).ToString("E")); } } else { ConfigNode power_node = config.AddNode("VESSEL_MICROWAVE_POWER_" + vesselID); power_node.AddValue("nuclear_power", MicrowavePowerTransmitter.getEnumeratedNuclearPowerForVessel(vessel).ToString("E")); power_node.AddValue("solar_power", MicrowavePowerTransmitter.getEnumeratedSolarPowerForVessel(vessel).ToString("E")); } if (config.HasNode("VESSEL_MICROWAVE_RELAY_" + vesselID)) { ConfigNode relay_node = config.GetNode("VESSEL_MICROWAVE_RELAY_" + vesselID); if (relay_node.HasValue("relay")) { relay_node.SetValue("relay", MicrowavePowerTransmitter.vesselIsRelay(vessel).ToString()); } else { relay_node.AddValue("relay", MicrowavePowerTransmitter.vesselIsRelay(vessel).ToString()); } } else { ConfigNode relay_node = config.AddNode("VESSEL_MICROWAVE_RELAY_" + vesselID); relay_node.AddValue("relay", MicrowavePowerTransmitter.vesselIsRelay(vessel).ToString()); } config.Save(PluginHelper.getPluginSaveFilePath()); } activeCount++; }
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 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++; }