Beispiel #1
0
		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);
		}
Beispiel #2
0
        // 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);
        }
Beispiel #3
0
  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;
    }
  }
Beispiel #4
0
        // 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>"));
                }
            }
        }
Beispiel #5
0
  // 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);
  }
Beispiel #6
0
 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;
 }
Beispiel #7
0
        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
        }
Beispiel #8
0
        // 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);
            }
        }
Beispiel #9
0
        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());
            }
        }
Beispiel #10
0
        // 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);
        }
Beispiel #11
0
  // 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;
  }
Beispiel #12
0
        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();
            }
        }
Beispiel #13
0
  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;
  }
Beispiel #14
0
        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);
        }
Beispiel #15
0
  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);
    }
  }
Beispiel #16
0
        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);
            }
        }
Beispiel #17
0
        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);
            }
        }
Beispiel #18
0
  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);
  }
Beispiel #19
0
        // 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);
        }
Beispiel #20
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)
			{
				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()));
		}
Beispiel #21
0
        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);
            }
        }
Beispiel #22
0
  // 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;
  }
Beispiel #23
0
 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();
   }
 }
Beispiel #24
0
		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;
				}
			}
		}
Beispiel #25
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;
    }
  }
Beispiel #26
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);
  }
Beispiel #27
0
  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;
      }
    }
  }
Beispiel #28
0
        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);
                    }
                }
            }
        }
Beispiel #29
0
        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);
        }
Beispiel #30
0
        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);
        }