// return true if a storm just ended // used to avoid sending 'signal is back' messages en-masse after the storm is over // - delta_time: time between calls to this function public static bool JustEnded(Vessel v, double delta_time) { // if in interplanetary space if (v.mainBody.flightGlobalsIndex == 0) { return(DB.Vessel(v).storm_age < delta_time * 2.0); } // if inside a planetary system else { return(DB.Body(Lib.PlanetarySystem(v.mainBody).name).storm_age < delta_time * 2.0); } }
// return true if a storm is in progress public static bool InProgress(Vessel v) { // if in interplanetary space if (v.mainBody.flightGlobalsIndex == 0) { return(DB.Vessel(v).storm_state == 2); } // if inside a planetary system else { return(DB.Body(Lib.PlanetarySystem(v.mainBody).name).storm_state == 2); } }
// return time left until CME is over public static double TimeLeftCME(Vessel v) { // if in interplanetary space if (v.mainBody.flightGlobalsIndex == 0) { VesselData vd = DB.Vessel(v); return(TimeLeftCME(vd.storm_time, vd.storm_age)); } // if inside a planetary system else { BodyData bd = DB.Body(Lib.PlanetarySystem(v.mainBody).name); return(TimeLeftCME(bd.storm_time, bd.storm_age)); } }
public static void Update(CelestialBody body, double elapsed_s) { // do nothing if storms are disabled if (!Features.SpaceWeather) { return; } // skip the sun if (body.flightGlobalsIndex == 0) { return; } // skip moons // note: referenceBody is never null here if (body.referenceBody.flightGlobalsIndex != 0) { return; } // get body data BodyData bd = DB.Body(body.name); // generate storm time if necessary if (bd.storm_time <= double.Epsilon) { bd.storm_time = Settings.StormMinTime + (Settings.StormMaxTime - Settings.StormMinTime) * Lib.RandomDouble(); } // accumulate age bd.storm_age += elapsed_s * Storm_Frequency(body.orbit.semiMajorAxis); // if storm is over if (bd.storm_age > bd.storm_time) { bd.storm_age = 0.0; bd.storm_time = 0.0; bd.storm_state = 0; } // if storm is in progress else if (bd.storm_age > bd.storm_time - Settings.StormDuration) { bd.storm_state = 2; } // if storm is incoming else if (bd.storm_age > bd.storm_time - Settings.StormDuration - Time_to_Impact(body.orbit.semiMajorAxis)) { bd.storm_state = 1; } // send messages // note: separed from state management to support the case when the user enter the SOI of a body under storm or about to be hit if (bd.msg_storm < 2 && bd.storm_state == 2) { if (Body_is_Relevant(body)) { Message.Post(Severity.danger, Lib.BuildString("The coronal mass ejection hit <b>", body.name, "</b> system"), Lib.BuildString("Storm duration: ", Lib.HumanReadableDuration(TimeLeftCME(bd.storm_time, bd.storm_age)))); } bd.msg_storm = 2; } else if (bd.msg_storm < 1 && bd.storm_state == 1) { if (Body_is_Relevant(body)) { Message.Post(Severity.warning, Lib.BuildString("Our observatories report a coronal mass ejection directed toward <b>", body.name, "</b> system"), Lib.BuildString("Time to impact: ", Lib.HumanReadableDuration(TimeBeforeCME(bd.storm_time, bd.storm_age)))); } bd.msg_storm = 1; } else if (bd.msg_storm > 1 && bd.storm_state == 0) { if (Body_is_Relevant(body)) { Message.Post(Severity.relax, Lib.BuildString("The solar storm at <b>", body.name, "</b> system is over")); } bd.msg_storm = 0; } }