void indicator_ec(Panel p, Vessel v, vessel_info vi) { resource_info ec = ResourceCache.Info(v, "ElectricCharge"); Supply supply = Profile.supplies.Find(k => k.resource == "ElectricCharge"); double low_threshold = supply != null ? supply.low_threshold : 0.15; double depletion = ec.Depletion(vi.crew_count); string tooltip = Lib.BuildString ( "<align=left /><b>name\tlevel\tduration</b>\n", ec.level <= 0.005 ? "<color=#ff0000>" : ec.level <= low_threshold ? "<color=#ffff00>" : "<color=#cccccc>", "EC\t", Lib.HumanReadablePerc(ec.level), "\t", depletion <= double.Epsilon ? "depleted" : Lib.HumanReadableDuration(depletion), "</color>" ); Texture image = ec.level <= 0.005 ? Icons.battery_red : ec.level <= low_threshold ? Icons.battery_yellow : Icons.battery_white; p.icon(image, tooltip); }
// return total radiation emitted in a vessel public static double Total(Vessel v) { // get resource cache resource_info ec = ResourceCache.Info(v, "ElectricCharge"); double tot = 0.0; if (v.loaded) { foreach (var emitter in Lib.FindModules <Emitter>(v)) { if (ec.amount > double.Epsilon || emitter.ec_rate <= double.Epsilon) { tot += emitter.running ? emitter.radiation : 0.0; } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Emitter")) { if (ec.amount > double.Epsilon || Lib.Proto.GetDouble(m, "ec_rate") <= double.Epsilon) { tot += Lib.Proto.GetBool(m, "running") ? Lib.Proto.GetDouble(m, "radiation") : 0.0; } } } return(tot); }
static void render_supplies(Panel p, Vessel v, vessel_info vi, vessel_resources resources) { // for each supply int supplies = 0; foreach(Supply supply in Profile.supplies) { // get resource info resource_info res = resources.Info(v, supply.resource); // only show estimate if the resource is present if (res.amount <= double.Epsilon) continue; // render panel title, if not done already if (supplies == 0) p.section("SUPPLIES"); // rate tooltip string rate_tooltip = Math.Abs(res.rate) >= 1e-10 ? Lib.BuildString ( res.rate > 0.0 ? "<color=#00ff00><b>" : "<color=#ff0000><b>", Lib.HumanReadableRate(Math.Abs(res.rate)), "</b></color>" ) : string.Empty; // determine label string label = supply.resource == "ElectricCharge" ? "battery" : Lib.SpacesOnCaps(supply.resource).ToLower(); // finally, render resource supply p.content(label, Lib.HumanReadableDuration(res.Depletion(vi.crew_count)), rate_tooltip); ++supplies; } }
// execute a script public void execute(Vessel v, ScriptType type) { // do nothing if there is no EC left on the vessel resource_info ec = ResourceCache.Info(v, "ElectricCharge"); if (ec.amount <= double.Epsilon) { return; } // get the script Script script; if (scripts.TryGetValue(type, out script)) { // execute the script script.execute(boot(v)); // show message to the user // - unless the script is empty (can happen when being edited) if (script.states.Count > 0 && DB.Vessel(v).cfg_script) { Message.Post(Lib.BuildString("Script called on vessel <b>", v.vesselName, "</b>")); } } }
// implement gravity ring mechanics for unloaded vessels public static void BackgroundUpdate(Vessel vessel, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, GravityRing ring, vessel_resources resources, double elapsed_s) { // get protomodule data float speed = Lib.Proto.GetFloat(m, "speed"); // get resource handler resource_info ec = resources.Info(vessel, "ElectricCharge"); // consume ec ec.Consume(ring.ec_rate * speed * elapsed_s * Reliability.Penalty(p, "GravityRing", 2.0)); // reset speed if there isn't enough ec // note: comparing against amount in previous simulation step if (ec.amount <= double.Epsilon) { speed = 0.0f; Lib.Proto.Set(m, "speed", speed); } // set entertainment // note: entertainmnent is only recomputed for loaded vessels, // so changing rate here does nothing until vessel is reloaded double rate = 1.0 + (ring.entertainment_rate - 1.0) * speed; Lib.Proto.Set(m, "rate", rate); }
GUIContent indicator_supplies(Vessel v, vessel_info vi) { GUIContent state = new GUIContent(); List<string> tooltips = new List<string>(); uint max_severity = 0; if (vi.crew_count > 0) { foreach(Rule r in Kerbalism.supply_rules) { resource_info res = ResourceCache.Info(v, r.resource_name); if (res.capacity > double.Epsilon) { double depletion = r.Depletion(v, res); string deplete_str = depletion <= double.Epsilon ? ", depleted" : double.IsNaN(depletion) ? "" : Lib.BuildString(", deplete in <b>", Lib.HumanReadableDuration(depletion), "</b>"); tooltips.Add(Lib.BuildString(r.resource_name, ": <b>", Lib.HumanReadablePerc(res.level), "</b>", deplete_str)); uint severity = res.level <= 0.005 ? 2u : res.level <= r.low_threshold ? 1u : 0; max_severity = Math.Max(max_severity, severity); } } } switch(max_severity) { case 0: state.image = icon_supplies_nominal; break; case 1: state.image = icon_supplies_warning; break; case 2: state.image = icon_supplies_danger; break; } state.tooltip = string.Join("\n", tooltips.ToArray()); return state; }
public KeyValuePair <bool, double> modReturn; // Return from DeviceEC public override void OnStart(StartState state) { // don't break tutorial scenarios & do something only in Flight scenario if (Lib.DisableScenario(this) || !Lib.IsFlight()) { return; } // cache list of modules module = part.FindModulesImplementing <PartModule>().FindLast(k => k.moduleName == type); // get energy from cache resources = ResourceCache.Info(vessel, "ElectricCharge"); hasEnergy = resources.amount > double.Epsilon; // Force the update to run at least once lastBrokenState = !isBroken; hasEnergyChanged = !hasEnergy; hasFixedEnergyChanged = !hasEnergy; #if DEBUG // setup UI Fields["actualCost"].guiActive = true; Fields["isBroken"].guiActive = true; #endif }
// execute the recipe public void Execute(Vessel v, vessel_resources resources) { // determine worst input ratio double worst_input = 1.0; foreach (var pair in inputs) { if (pair.Value > double.Epsilon) //< avoid division by zero { resource_info res = resources.Info(v, pair.Key); worst_input = Math.Min(worst_input, Math.Max(0.0, res.amount + res.deferred) / pair.Value); } } // consume inputs foreach (var pair in inputs) { resource_info res = resources.Info(v, pair.Key); res.Consume(pair.Value * worst_input); } // produce outputs foreach (var pair in outputs) { resource_info res = resources.Info(v, pair.Key); res.Produce(pair.Value * worst_input); } }
static void ProcessConverter(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, ModuleResourceConverter converter, vessel_resources resources, double elapsed_s) { // note: ignore stock temperature mechanic of converters // note: ignore autoshutdown // note: using hard-coded crew bonus values from the wiki because the module data make zero sense (DERP ALERT) // note: non-mandatory resources 'dynamically scale the ratios', that is exactly what mandatory resources do too (DERP ALERT) // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation) // note: support PlanetaryBaseSystem converters // note: support NearFuture reactors // note: assume dump overboard is false for all outputs // if active if (Lib.Proto.GetBool(m, "IsActivated")) { // determine if vessel is full of all output resources // note: comparing against previous amount bool full = true; foreach (var or in converter.outputList) { resource_info res = resources.Info(v, or.ResourceName); full &= (res.level >= converter.FillAmount - double.Epsilon); } // if not full if (!full) { // deduce crew bonus int exp_level = -1; if (converter.UseSpecialistBonus) { foreach (ProtoCrewMember c in Lib.CrewList(v)) { if (c.experienceTrait.Effects.Find(k => k.Name == converter.ExperienceEffect) != null) { exp_level = Math.Max(exp_level, c.experienceLevel); } } } double exp_bonus = exp_level < 0 ? 1.0 : 5.0 + (double)exp_level * 4.0; // create and commit recipe resource_recipe recipe = new resource_recipe(); foreach (var ir in converter.inputList) { recipe.Input(ir.ResourceName, ir.Ratio * elapsed_s); } foreach (var or in converter.outputList) { recipe.Output(or.ResourceName, or.Ratio * exp_bonus * elapsed_s); } resources.Transform(recipe); } // undo stock behaviour by forcing last_update_time to now Lib.Proto.Set(m, "lastUpdateTime", Planetarium.GetUniversalTime()); } }
// execute the recipe public bool Execute(Vessel v, vessel_resources resources) { // determine worst input ratio // - pure input recipes can just underflow double worst_input = left; if (outputs.Count > 0) { for (int i = 0; i < inputs.Count; ++i) { entry e = inputs[i]; resource_info res = resources.Info(v, e.name); worst_input = Lib.Clamp((res.amount + res.deferred) * e.inv_quantity, 0.0, worst_input); } } // determine worst output ratio // - pure output recipes can just overflow double worst_output = left; if (inputs.Count > 0) { for (int i = 0; i < outputs.Count; ++i) { entry e = outputs[i]; if (!e.dump) // ignore outputs that can dump overboard { resource_info res = resources.Info(v, e.name); worst_output = Lib.Clamp((res.capacity - (res.amount + res.deferred)) * e.inv_quantity, 0.0, worst_output); } } } // determine worst-io double worst_io = Math.Min(worst_input, worst_output); // consume inputs for (int i = 0; i < inputs.Count; ++i) { entry e = inputs[i]; resources.Consume(v, e.name, e.quantity * worst_io); } // produce outputs for (int i = 0; i < outputs.Count; ++i) { entry e = outputs[i]; resources.Produce(v, e.name, e.quantity * worst_io); } // update amount left to execute left -= worst_io; // the recipe was executed, at least partially return(worst_io > double.Epsilon); }
// implement gravity ring mechanics public void FixedUpdate() { // reset speed when not open if (!opened) speed = 0.0f; // hide the tweakable if not open this.Fields["speed"].guiActive = opened; this.Fields["speed"].guiActiveEditor = opened; // manage animation if (rotate != null) { // set rotating animation speed rotate[rotate_animation].speed = speed; // if its open but no animations are playing, start rotating if (opened) { bool playing = false; foreach(var anim in this.part.FindModelAnimators()) { playing |= anim.isPlaying; } if (!playing) rotate.Play(rotate_animation); } } // do nothing else in the editor if (HighLogic.LoadedSceneIsEditor) return; // get vessel info from the cache vessel_info vi = Cache.VesselInfo(vessel); // do nothing if vessel is invalid if (!vi.is_valid) return; // get resource cache vessel_resources resources = ResourceCache.Get(vessel); // get resource handler resource_info ec = resources.Info(vessel, "ElectricCharge"); // consume ec ec.Consume(ec_rate * speed * Kerbalism.elapsed_s * vi.time_dilation); // reset speed if there isn't enough ec // note: comparing against amount in previous simulation step if (ec.amount <= double.Epsilon) speed = 0.0f; // set entertainment rate = 1.0 + (entertainment_rate - 1.0) * speed; }
public override void OnUpdate() { if (!Lib.IsFlight() || module == null) { return; } // get energy from cache resources = ResourceCache.Info(vessel, "ElectricCharge"); hasEnergy = resources.amount > double.Epsilon; // Update UI only if hasEnergy has changed or if is broken state has changed if (isBroken) { if (isBroken != lastBrokenState) { lastBrokenState = isBroken; Update_UI(!isBroken); } } else if (hasEnergyChanged != hasEnergy) { Lib.Debug("Energy state has changed: {0}", hasEnergy); hasEnergyChanged = hasEnergy; lastBrokenState = false; // Update UI Update_UI(hasEnergy); } // Constantly Update UI for special modules if (isBroken) { Constant_OnGUI(!isBroken); } else { Constant_OnGUI(hasEnergy); } if (!hasEnergy || isBroken) { actualCost = 0; isConsuming = false; } else { isConsuming = GetIsConsuming(); } }
GUIContent indicator_ec(Vessel v) { resource_info ec = ResourceCache.Info(v, "ElectricCharge"); GUIContent state = new GUIContent(); state.tooltip = ec.capacity > 0.0 ? "EC: " + Lib.HumanReadablePerc(ec.level) : ""; state.image = icon_battery_nominal; double low_threshold = 0.15; if (Kerbalism.ec_rule != null) low_threshold = Kerbalism.ec_rule.low_threshold; if (ec.level <= 0.005) state.image = icon_battery_danger; else if (ec.level <= low_threshold) state.image = icon_battery_warning; return state; }
static void ProcessCryoTank(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule simple_boiloff, vessel_resources resources, double elapsed_s) { // note: cryotank module already does a post-facto simulation of background boiling, and we could use that for the boiling // however, it also does simulate the ec consumption that way, so we have to disable the post-facto simulation IList fuels = Lib.PrivateField <IList>(simple_boiloff.GetType(), simple_boiloff, "fuels"); foreach (object cryoFuel in fuels) { string fuel_name = Lib.PrivateField <string> (cryoFuel.GetType(), cryoFuel, "fuelName"); float boiloff_rate_percent = Lib.PrivateField <float> (cryoFuel.GetType(), cryoFuel, "boiloffRate"); // get resource handlers resource_info ec = resources.Info(v, "ElectricCharge"); resource_info fuel = resources.Info(v, fuel_name); // if there is some fuel // note: comparing against amount in previous simulation step if (fuel.amount > double.Epsilon) { // get capacity in the part double capacity = p.resources.Find(k => k.resourceName == fuel_name).maxAmount; // if cooling is enabled and there was enough ec // note: comparing against amount in previous simulation step if (Lib.Proto.GetBool(m, "CoolingEnabled") && ec.amount > double.Epsilon) { // get cooling ec cost per 1000 units of fuel, per-second double cooling_cost = Lib.ReflectionValue <float>(simple_boiloff, "CoolingCost"); // consume ec ec.Consume(cooling_cost * capacity * 0.001 * elapsed_s); } // if there wasn't ec, or if cooling is disabled else { // get boiloff rate in proportion to fuel amount, per-second double boiloff_rate = boiloff_rate_percent * 0.00000277777; // let it boil off fuel.Consume(capacity * (1.0 - Math.Pow(1.0 - boiloff_rate, elapsed_s))); } } } // disable post-facto simulation Lib.Proto.Set(m, "LastUpdateTime", v.missionTime); }
public static void update(Vessel v) { // get kerbal data from db kerbal_data kd = KerbalData(v); // get KerbalEVA module KerbalEVA kerbal = v.FindPartModulesImplementing<KerbalEVA>()[0]; // show/hide helmet, play nice with KIS if (!Kerbalism.detected_mods.KIS) { SetHelmet(kerbal, kd.has_helmet); } // synchronize has_helmet state with KIS (for the headlights) else { kd.has_helmet = HasHelmet(kerbal); } // get resource handler resource_info ec = ResourceCache.Info(v, "ElectricCharge"); // consume EC for the headlamp if (kd.has_helmet && kerbal.lampOn) ec.Consume(Settings.HeadlightCost * Kerbalism.elapsed_s); //< ignore time dilation // force the headlamp lights on/off depending on ec amount left and if it has an helmet // synchronize helmet flares with headlamp state // support case when there is no ec rule (or no profile at all) bool b = kd.has_helmet && kerbal.lampOn && (ec.amount > double.Epsilon || ec.capacity <= double.Epsilon); SetHeadlamp(kerbal, b); SetFlares(kerbal, b); // if dead if (kd.eva_dead) { // enforce freezed state SetFreezed(kerbal); // remove plant flag action kerbal.flagItems = 0; // remove experiment actions (game engine keeps readding them) RemoveExperiments(kerbal); } }
public void FixedUpdate() { // do nothing in the editor if (Lib.IsEditor()) { return; } // if the module is either non-deployable or deployed if (deploy.Length == 0 || deployed) { // get resource handler resource_info ec = ResourceCache.Info(vessel, "ElectricCharge"); // consume ec ec.Consume(ec_rate * Kerbalism.elapsed_s); } }
public void FixedUpdate() { // do nothing in the editor if (Lib.IsEditor()) { return; } // if enabled, and there is ec consumption if (running && ec_rate > double.Epsilon) { // get resource cache resource_info ec = ResourceCache.Info(vessel, "ElectricCharge"); // consume EC ec.Consume(ec_rate * Kerbalism.elapsed_s); } }
void indicator_ec(Panel p, Vessel v) { Texture image; string tooltip; resource_info ec = ResourceCache.Info(v, "ElectricCharge"); tooltip = ec.capacity > 0.0 ? "EC: " + Lib.HumanReadablePerc(ec.level) : ""; image = Icons.battery_white; Supply supply = Profile.supplies.Find(k => k.resource == "ElectricCharge"); double low_threshold = supply != null ? supply.low_threshold : 0.15; if (ec.level <= 0.005) image = Icons.battery_red; else if (ec.level <= low_threshold) image = Icons.battery_yellow; p.icon(image, tooltip); }
// return a resource handler public resource_info Info(Vessel v, string resource_name) { // try to get existing entry if any resource_info res; if (resources.TryGetValue(resource_name, out res)) { return(res); } // create new entry res = new resource_info(v, resource_name); // remember new entry resources.Add(resource_name, res); // return new entry return(res); }
void indicator_supplies(Panel p, Vessel v, vessel_info vi) { List<string> tooltips = new List<string>(); uint max_severity = 0; if (vi.crew_count > 0) { foreach (Supply supply in Profile.supplies.FindAll(k => k.resource != "ElectricCharge")) { resource_info res = ResourceCache.Info(v, supply.resource); double depletion = res.Depletion(vi.crew_count); if (res.capacity > double.Epsilon) { if (tooltips.Count == 0) { tooltips.Add("<align=left /><b>name\t\tlevel\tduration</b>"); } tooltips.Add(Lib.BuildString ( res.level <= 0.005 ? "<color=#ff0000>" : res.level <= supply.low_threshold ? "<color=#ffff00>" : "<color=#cccccc>", supply.resource, supply.resource != "Ammonia" ? "\t\t" : "\t", //< hack: make ammonia fit damn it Lib.HumanReadablePerc(res.level), "\t", depletion <= double.Epsilon ? "depleted" : Lib.HumanReadableDuration(depletion), "</color>" )); uint severity = res.level <= 0.005 ? 2u : res.level <= supply.low_threshold ? 1u : 0; max_severity = Math.Max(max_severity, severity); } } } Texture image = max_severity == 2 ? Icons.box_red : max_severity == 1 ? Icons.box_yellow : Icons.box_white; p.icon(image, string.Join("\n", tooltips.ToArray())); }
State venting() { // in flight if (Lib.IsFlight()) { // shortcuts resource_info vessel_atmo = ResourceCache.Info(vessel, "Atmosphere"); PartResource hab_atmo = part.Resources["Atmosphere"]; // get amount of atmosphere in part double hab_amount = hab_atmo.amount; // venting succeeded if the amount reached zero if (hab_amount <= double.Epsilon) { return(State.disabled); } // determine venting speed double amount = volume * equalize_speed * Kerbalism.elapsed_s; // consume from the part, clamp amount to what's available in the part amount = Math.Min(amount, hab_atmo.amount); hab_atmo.amount -= amount; // produce in all enabled habs in the vessel // (attempt recovery, but dump overboard if there is no capacity left) vessel_atmo.Produce(amount); // venting still in progress return(State.venting); } // in the editors else { // set amount to zero part.Resources["Atmosphere"].amount = 0.0; // return new state return(State.disabled); } }
// return seconds until depletion, 0.0 if there is no resource and NaN if it will never deplete public double Depletion(Vessel v, resource_info res) { // [unused] Newton–Raphson, 1 step // C = amount // R = delta // A = change in delta // t0 = C / -R // eyeball estimate // F' = 0.5 * t0 * t0 // differential of F // F = C + R * t0 + A * F' // equation of motion, constant acceleration // t1 = t0 - F / F' // time until depletion // calculate rate of change from interval-based rule double meal_rate = interval > double.Epsilon ? rate / interval : 0.0; // calculate total rate of change double delta = res.rate - meal_rate * Lib.CrewCount(v); // return depletion return res.amount <= double.Epsilon ? 0.0 : delta >= -0.000001 ? double.NaN : res.amount / -delta; }
void render_supplies(Vessel v, vessel_info vi) { if (Kerbalism.supply_rules.Count > 0 || Kerbalism.ec_rule != null) { render_title("SUPPLIES"); if (Kerbalism.ec_rule != null) { resource_info res = ResourceCache.Info(v, "ElectricCharge"); render_content("battery", res.level > double.Epsilon ? Lib.HumanReadableDuration(Kerbalism.ec_rule.Depletion(v, res)) : "none", res.rate); } if (vi.crew_capacity > 0) { foreach(Rule r in Kerbalism.supply_rules) { resource_info res = ResourceCache.Info(v, r.resource_name); render_content(r.resource_name.AddSpacesOnCaps().ToLower(), res.level > double.Epsilon ? Lib.HumanReadableDuration(r.Depletion(v, res)) : "none", res.rate); } } render_space(); } }
public void Execute(Vessel v, VesselData vd, vessel_resources resources) { // get crew List<ProtoCrewMember> crew = Lib.CrewList(v); // get resource handler resource_info res = resources.Info(v, resource); // get data from db SupplyData sd = DB.Vessel(v).Supply(resource); // message obey user config bool show_msg = resource == "ElectricCharge" ? vd.cfg_ec : vd.cfg_supply; // messages are shown only if there is some capacity and the vessel is manned // special case: ElectricCharge related messages are shown for unmanned vessels too if (res.capacity > double.Epsilon && (crew.Count > 0 || resource == "ElectricCharge")) { // manned/probe message variant uint variant = crew.Count > 0 ? 0 : 1u; // manage messages if (res.level <= double.Epsilon && sd.message < 2) { if (empty_message.Length > 0 && show_msg) Message.Post(Severity.danger, Lib.ExpandMsg(empty_message, v, null, variant)); sd.message = 2; } else if (res.level < low_threshold && sd.message < 1) { if (low_message.Length > 0 && show_msg) Message.Post(Severity.warning, Lib.ExpandMsg(low_message, v, null, variant)); sd.message = 1; } else if (res.level > low_threshold && sd.message > 0) { if (refill_message.Length > 0 && show_msg) Message.Post(Severity.relax, Lib.ExpandMsg(refill_message, v, null, variant)); sd.message = 0; } } }
public static void update(Vessel v) { // do nothing if not an eva kerbal if (!v.isEVA) return; // get KerbalEVA module KerbalEVA kerbal = Lib.FindModules<KerbalEVA>(v)[0]; // get resource handler resource_info ec = ResourceCache.Info(v, "ElectricCharge"); // determine if headlamps need ec // - not required if there is no EC capacity in eva kerbal (no ec supply in profile) // - not required if no EC cost for headlamps is specified (set by the user) bool need_ec = ec.capacity > double.Epsilon && Settings.HeadLampsCost > double.Epsilon; // consume EC for the headlamps if (need_ec && kerbal.lampOn) { ec.Consume(Settings.HeadLampsCost * Kerbalism.elapsed_s); } // force the headlamps on/off HeadLamps(kerbal, kerbal.lampOn && (!need_ec || ec.amount > double.Epsilon)); // if dead if (IsDead(v)) { // enforce freezed state Freeze(kerbal); // disable modules DisableModules(kerbal); // remove plant flag action kerbal.flagItems = 0; } }
void indicator_supplies(Panel p, Vessel v, vessel_info vi) { List<string> tooltips = new List<string>(); uint max_severity = 0; if (vi.crew_count > 0) { var supplies = Profile.supplies.FindAll(k => k.resource != "ElectricCharge"); foreach(Supply supply in supplies) { resource_info res = ResourceCache.Info(v, supply.resource); if (res.capacity > double.Epsilon) { double depletion = res.Depletion(vi.crew_count); string deplete_str = depletion <= double.Epsilon ? ", depleted" : double.IsNaN(depletion) ? "" : Lib.BuildString(", deplete in <b>", Lib.HumanReadableDuration(depletion), "</b>"); tooltips.Add(Lib.BuildString(supply.resource, ": <b>", Lib.HumanReadablePerc(res.level), "</b>", deplete_str)); uint severity = res.level <= 0.005 ? 2u : res.level <= supply.low_threshold ? 1u : 0; max_severity = Math.Max(max_severity, severity); } } } Texture image = Icons.box_white; switch(max_severity) { case 0: image = Icons.box_white; break; case 1: image = Icons.box_yellow; break; case 2: image = Icons.box_red; break; } string tooltip = string.Join("\n", tooltips.ToArray()); p.icon(image, tooltip); }
public void FixedUpdate() { // in any scene: update the RMB ui Status = Lib.HumanReadableRadiationRate(Math.Abs(radiation) * intensity); // do nothing else in the editor if (HighLogic.LoadedSceneIsEditor) return; // if there is ec consumption if (ec_rate > double.Epsilon) { // get vessel info from the cache vessel_info vi = Cache.VesselInfo(vessel); // do nothing if vessel is invalid if (!vi.is_valid) return; // get resource cache resource_info ec = ResourceCache.Info(vessel, "ElectricCharge"); // get elapsed time double elapsed_s = Kerbalism.elapsed_s * vi.time_dilation; // if there is enough EC // note: comparing against amount in previous simulation step if (ec.amount > double.Epsilon) { // consume EC ec.Consume(ec_rate * intensity * elapsed_s); } // else disable it else { intensity = 0.0f; } } }
public void FixedUpdate() { // in flight if (Lib.IsFlight()) { // if we are transmitting using the stock system if (stream.transmitting()) { // get ec resource handler resource_info ec = ResourceCache.Info(vessel, "ElectricCharge"); // if we are still linked, and there is ec left if (CanTransmit() && ec.amount > double.Epsilon) { // compression factor // - used to avoid making the user wait too much for transmissions that // don't happen in background, while keeping transmission rates realistic const double compression = 16.0; // transmit using the data stream stream.update(DataRate * Kerbalism.elapsed_s * compression, vessel); // consume ec ec.Consume(DataResourceCost * Kerbalism.elapsed_s); } else { // abort transmission, return data to the vessel stream.abort(vessel); // inform the user ScreenMessages.PostScreenMessage("Transmission aborted", 5.0f, ScreenMessageStyle.UPPER_LEFT); } } } }
static void ProcessRadioisotopeGenerator(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule radioisotope_generator, resource_info ec, double elapsed_s) { // note: doesn't support easy mode double power = Lib.ReflectionValue <float>(radioisotope_generator, "BasePower"); double half_life = Lib.ReflectionValue <float>(radioisotope_generator, "HalfLife"); double mission_time = v.missionTime / (3600.0 * Lib.HoursInDay() * Lib.DaysInYear()); double remaining = Math.Pow(2.0, (-mission_time) / half_life); ec.Produce(power * remaining * elapsed_s); }
static void ProcessFissionGenerator(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule fission_generator, resource_info ec, double elapsed_s) { // note: ignore heat double power = Lib.ReflectionValue <float>(fission_generator, "PowerGeneration"); var reactor = p.modules.Find(k => k.moduleName == "FissionReactor"); double tweakable = reactor == null ? 1.0 : Lib.ConfigValue(reactor.moduleValues, "CurrentPowerPercent", 100.0) * 0.01; ec.Produce(power * tweakable * elapsed_s); }