Esempio n. 1
0
		public Vessel_info(Vessel v, uint vessel_id, UInt64 inc)
		{
			// NOTE: anything used here can't in turn use cache, unless you know what you are doing

			// NOTE: you can't cache vessel position
			// at any point in time all vessel/body positions are relative to a different frame of reference
			// so comparing the current position of a vessel, with the cached one of another make no sense

			// associate with an unique incremental id
			this.inc = inc;

			// determine if this is a valid vessel
			is_vessel = Lib.IsVessel(v);
			if (!is_vessel)
				return;

			// determine if this is a rescue mission vessel
			is_rescue = Misc.IsRescueMission(v);
			if (is_rescue)
				return;

			// dead EVA are not valid vessels
			if (EVA.IsDead(v))
				return;

			// shortcut for common tests
			is_valid = true;

			// generate id once
			id = vessel_id;

			// calculate crew info for the vessel
			crew_count = Lib.CrewCount(v);
			crew_capacity = Lib.CrewCapacity(v);

			// get vessel position
			Vector3d position = Lib.VesselPosition(v);

			// this should never happen again
			if (Vector3d.Distance(position, v.mainBody.position) < 1.0)
			{
				throw new Exception("Shit hit the fan for vessel " + v.vesselName);
			}

			// determine if there is enough EC for a powered state
			powered = ResourceCache.Info(v, "ElectricCharge").amount > double.Epsilon;

			// determine if in sunlight, calculate sun direction and distance
			sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0;

			// environment stuff
			atmo_factor = Sim.AtmosphereFactor(v.mainBody, position, sun_dir);
			gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude);
			underwater = Sim.Underwater(v);
			breathable = Sim.Breathable(v, underwater);
			landed = Lib.Landed(v);
			zerog = !landed && (!v.mainBody.atmosphere || v.mainBody.atmosphereDepth < v.altitude);

			if (v.mainBody.flightGlobalsIndex != 0 && TimeWarp.CurrentRate > 1000.0f)
			{
				highspeedWarp(v);
			}

			// temperature at vessel position
			temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux);
			temp_diff = Sim.TempDiff(temperature, v.mainBody, landed);

			// radiation
			radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out magnetosphere, out inner_belt, out outer_belt, out interstellar);

			// extended atmosphere
			thermosphere = Sim.InsideThermosphere(v);
			exosphere = Sim.InsideExosphere(v);

			// malfunction stuff
			malfunction = Reliability.HasMalfunction(v);
			critical = Reliability.HasCriticalFailure(v);

			// communications info
			connection = new ConnectionInfo(v, powered, blackout);
			transmitting = Science.Transmitting(v, connection.linked && connection.rate > double.Epsilon);

			// habitat data
			volume = Habitat.Tot_volume(v);
			surface = Habitat.Tot_surface(v);
			pressure = Habitat.Pressure(v);
			poisoning = Habitat.Poisoning(v);
			humidity = Habitat.Humidity(v);
			shielding = Habitat.Shielding(v);
			living_space = Habitat.Living_space(v);
			comforts = new Comforts(v, landed, crew_count > 1, connection.linked && connection.rate > double.Epsilon);

			// data about greenhouses
			greenhouses = Greenhouse.Greenhouses(v);

			// other stuff
			gravioli = Sim.Graviolis(v);
		}
Esempio n. 2
0
        void FixedUpdate()
        {
            // remove control locks in any case
            Misc.ClearLocks();

            // do nothing if paused
            if (Lib.IsPaused())
            {
                return;
            }

            // maintain elapsed_s, converting to double only once
            // and detect warp blending
            double fixedDeltaTime = TimeWarp.fixedDeltaTime;

            if (Math.Abs(fixedDeltaTime - elapsed_s) > double.Epsilon)
            {
                warp_blending = 0;
            }
            else
            {
                ++warp_blending;
            }
            elapsed_s = fixedDeltaTime;

            // evict oldest entry from vessel cache
            Cache.Update();

            // store info for oldest unloaded vessel
            double           last_time      = 0.0;
            Vessel           last_v         = null;
            Vessel_info      last_vi        = null;
            VesselData       last_vd        = null;
            Vessel_resources last_resources = null;

            // for each vessel
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // get vessel info from the cache
                Vessel_info vi = Cache.VesselInfo(v);

                // set locks for active vessel
                if (v.isActiveVessel)
                {
                    Misc.SetLocks(v, vi);
                }

                // maintain eva dead animation and helmet state
                if (v.loaded && v.isEVA)
                {
                    EVA.Update(v);
                }

                // keep track of rescue mission kerbals, and gift resources to their vessels on discovery
                if (v.loaded && vi.is_vessel)
                {
                    // manage rescue mission mechanics
                    Misc.ManageRescueMission(v);
                }

                // do nothing else for invalid vessels
                if (!vi.is_valid)
                {
                    continue;
                }

                // get vessel data from db
                VesselData vd = DB.Vessel(v);

                // get resource cache
                Vessel_resources resources = ResourceCache.Get(v);

                // if loaded
                if (v.loaded)
                {
                    // get most used resource
                    Resource_info ec = resources.Info(v, "ElectricCharge");

                    // show belt warnings
                    Radiation.BeltWarnings(v, vi, vd);

                    // update storm data
                    Storm.Update(v, vi, vd, elapsed_s);

                    Communications.Update(v, vi, vd, ec, elapsed_s);

                    // Habitat equalization
                    ResourceBalance.Equalizer(v);

                    // transmit science data
                    Science.Update(v, vi, vd, resources, elapsed_s);

                    // apply rules
                    Profile.Execute(v, vi, vd, resources, elapsed_s);

                    // apply deferred requests
                    resources.Sync(v, elapsed_s);

                    // call automation scripts
                    vd.computer.Automate(v, vi, resources);

                    // remove from unloaded data container
                    unloaded.Remove(vi.id);
                }
                // if unloaded
                else
                {
                    // get unloaded data, or create an empty one
                    Unloaded_data ud;
                    if (!unloaded.TryGetValue(vi.id, out ud))
                    {
                        ud = new Unloaded_data();
                        unloaded.Add(vi.id, ud);
                    }

                    // accumulate time
                    ud.time += elapsed_s;

                    // maintain oldest entry
                    if (ud.time > last_time)
                    {
                        last_time      = ud.time;
                        last_v         = v;
                        last_vi        = vi;
                        last_vd        = vd;
                        last_resources = resources;
                    }
                }
            }

            // at most one vessel gets background processing per physics tick
            // if there is a vessel that is not the currently loaded vessel, then
            // we will update the vessel whose most recent background update is the oldest
            if (last_v != null)
            {
                // get most used resource
                Resource_info last_ec = last_resources.Info(last_v, "ElectricCharge");

                // show belt warnings
                Radiation.BeltWarnings(last_v, last_vi, last_vd);

                // update storm data
                Storm.Update(last_v, last_vi, last_vd, last_time);

                Communications.Update(last_v, last_vi, last_vd, last_ec, last_time);

                // transmit science	data
                Science.Update(last_v, last_vi, last_vd, last_resources, last_time);

                // apply rules
                Profile.Execute(last_v, last_vi, last_vd, last_resources, last_time);

                // simulate modules in background
                Background.Update(last_v, last_vi, last_vd, last_resources, last_time);

                // apply deferred requests
                last_resources.Sync(last_v, last_time);

                // call automation scripts
                last_vd.computer.Automate(last_v, last_vi, last_resources);

                // remove from unloaded data container
                unloaded.Remove(last_vi.id);
            }

            // update storm data for one body per-step
            if (storm_bodies.Count > 0)
            {
                storm_bodies.ForEach(k => k.time += elapsed_s);
                Storm_data sd = storm_bodies[storm_index];
                Storm.Update(sd.body, sd.time);
                sd.time     = 0.0;
                storm_index = (storm_index + 1) % storm_bodies.Count;
            }
        }
Esempio n. 3
0
        public override void OnLoad(ConfigNode node)
        {
            // deserialize data
            DB.Load(node);

            Communications.NetworkInitialized  = false;
            Communications.NetworkInitializing = false;

            // initialize everything just once
            if (!initialized)
            {
                // add supply resources to pods
                Profile.SetupPods();

                // initialize subsystems
                Cache.Init();
                ResourceCache.Init();
                Radiation.Init();
                Science.Init();
                LineRenderer.Init();
                ParticleRenderer.Init();
                Highlighter.Init();
                UI.Init();

                // prepare storm data
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (Storm.Skip_body(body))
                    {
                        continue;
                    }
                    Storm_data sd = new Storm_data
                    {
                        body = body
                    };
                    storm_bodies.Add(sd);
                }

                // various tweaks to the part icons in the editor
                Misc.TweakPartIcons();

                // setup callbacks
                callbacks = new Callbacks();

                // everything was initialized
                initialized = true;
            }

            // detect if this is a different savegame
            if (DB.uid != savegame_uid)
            {
                // clear caches
                Cache.Clear();
                ResourceCache.Clear();
                Message.all_logs.Clear();

                // sync main window pos from db
                UI.Sync();

                // remember savegame id
                savegame_uid = DB.uid;
            }
        }
Esempio n. 4
0
        public void Execute(Vessel v, Vessel_info vi, Vessel_resources resources, double elapsed_s)
        {
            // store list of crew to kill
            List <ProtoCrewMember> deferred_kills = new List <ProtoCrewMember>();

            // get input resource handler
            Resource_info res = input.Length > 0 ? resources.Info(v, input) : null;

            // determine message variant
            uint variant = vi.temperature < PreferencesLifeSupport.Instance.survivalTemperature ? 0 : 1u;

            // get product of all environment modifiers
            double k = Modifiers.Evaluate(v, vi, resources, modifiers);

            bool lifetime_enabled = PreferencesBasic.Instance.lifetime;

            // for each crew
            foreach (ProtoCrewMember c in Lib.CrewList(v))
            {
                // get kerbal data
                KerbalData kd = DB.Kerbal(c.name);

                // skip rescue kerbals
                if (kd.rescue)
                {
                    continue;
                }

                // skip disabled kerbals
                if (kd.disabled)
                {
                    continue;
                }

                // get kerbal property data from db
                RuleData rd = kd.Rule(name);
                rd.lifetime = lifetime_enabled && lifetime;

                // if continuous
                double step;
                if (interval <= double.Epsilon)
                {
                    // influence consumption by elapsed time
                    step = elapsed_s;
                }
                // if interval-based
                else
                {
                    // accumulate time
                    rd.time_since += elapsed_s;

                    // determine number of steps
                    step = Math.Floor(rd.time_since / interval);

                    // consume time
                    rd.time_since -= step * interval;

                    // remember if a meal is consumed/produced in this simulation step
                    if (step > 0.99)
                    {
                        res.SetMealHappened();
                    }
                    if (output.Length > 0 && step > 0.99)
                    {
                        ResourceCache.Info(v, output).SetMealHappened();
                    }
                }

                // if continuous, or if one or more intervals elapsed
                if (step > double.Epsilon)
                {
                    double r = rate * Variance(name, c, individuality);                      // kerbal-specific variance

                    // if there is a resource specified
                    if (res != null && r > double.Epsilon)
                    {
                        // determine amount of resource to consume
                        double required = r                                   // consumption rate
                                          * k                                 // product of environment modifiers
                                          * step;                             // seconds elapsed or number of steps

                        // if there is no output
                        if (output.Length == 0)
                        {
                            // simply consume (that is faster)
                            res.Consume(required, name);
                        }
                        // if there is an output and monitor is false
                        else if (!monitor)
                        {
                            // transform input into output resource
                            // - rules always dump excess overboard (because it is waste)
                            Resource_recipe recipe = new Resource_recipe((Part)null, name);                              // kerbals are not associated with a part
                            recipe.Input(input, required);
                            recipe.Output(output, required * ratio, true);
                            resources.Transform(recipe);
                        }
                        // if monitor then do not consume input resource and only produce output if resource percentage + monitor_offset is < 100%
                        else if ((res.amount / res.capacity) + monitor_offset < 1.0)
                        {
                            // simply produce (that is faster)
                            resources.Produce(v, output, required * ratio, name);
                        }
                    }

                    // degenerate:
                    // - if the environment modifier is not telling to reset (by being zero)
                    // - if the input threshold is reached if used
                    // - if this rule is resource-less, or if there was not enough resource in the vessel
                    if (input_threshold >= double.Epsilon)
                    {
                        if (res.amount >= double.Epsilon && res.capacity >= double.Epsilon)
                        {
                            trigger = (res.amount / res.capacity) + monitor_offset >= input_threshold;
                        }
                        else
                        {
                            trigger = false;
                        }
                    }
                    else
                    {
                        trigger = input.Length == 0 || res.amount <= double.Epsilon;
                    }

                    if (k > 0.0 && trigger)
                    {
                        rd.problem += degeneration                                   // degeneration rate per-second or per-interval
                                      * k                                            // product of environment modifiers
                                      * step                                         // seconds elapsed or by number of steps
                                      * Variance(name, c, variance);                 // kerbal-specific variance
                    }
                    // else slowly recover
                    else
                    {
                        rd.problem *= 1.0 / (1.0 + Math.Max(interval, 1.0) * step * 0.002);
                    }
                }

                bool do_breakdown = false;

                if (breakdown && PreferencesBasic.Instance.stressBreakdowns)
                {
                    // stress level
                    double breakdown_probability = rd.problem / warning_threshold;
                    breakdown_probability = Lib.Clamp(breakdown_probability, 0.0, 1.0);

                    // use the stupidity of a kerbal.
                    // however, nobody is perfect - not even a kerbal with a stupidity of 0.
                    breakdown_probability *= c.stupidity * 0.6 + 0.4;

                    // apply the weekly error rate
                    breakdown_probability *= PreferencesBasic.Instance.stressBreakdownRate;

                    // now we have the probability for one failure per week, based on the
                    // individual stupidity and stress level of the kerbal.

                    breakdown_probability = (breakdown_probability * elapsed_s) / (Lib.DaysInYear() * Lib.HoursInDay() * 3600);
                    if (breakdown_probability > Lib.RandomDouble())
                    {
                        do_breakdown = true;

                        // we're stressed out and just made a major mistake, this further increases the stress level...
                        rd.problem += warning_threshold * 0.05;                         // add 5% of the warning treshold to current stress level
                    }
                }

                // kill kerbal if necessary
                if (rd.problem >= fatal_threshold)
                {
                    if (fatal_message.Length > 0)
                    {
                        Message.Post(breakdown ? Severity.breakdown : Severity.fatality, Lib.ExpandMsg(fatal_message, v, c, variant));
                    }

                    if (breakdown)
                    {
                        do_breakdown = true;

                        // move back between warning and danger level
                        rd.problem = (warning_threshold + danger_threshold) * 0.5;

                        // make sure next danger message is shown
                        rd.message = 1;
                    }
                    else
                    {
                        deferred_kills.Add(c);
                    }
                }
                // show messages
                else if (rd.problem >= danger_threshold && rd.message < 2)
                {
                    if (danger_message.Length > 0)
                    {
                        Message.Post(Severity.danger, Lib.ExpandMsg(danger_message, v, c, variant));
                    }
                    rd.message = 2;
                }
                else if (rd.problem >= warning_threshold && rd.message < 1)
                {
                    if (warning_message.Length > 0)
                    {
                        Message.Post(Severity.warning, Lib.ExpandMsg(warning_message, v, c, variant));
                    }
                    rd.message = 1;
                }
                else if (rd.problem < warning_threshold && rd.message > 0)
                {
                    if (relax_message.Length > 0)
                    {
                        Message.Post(Severity.relax, Lib.ExpandMsg(relax_message, v, c, variant));
                    }
                    rd.message = 0;
                }

                if (do_breakdown)
                {
                    // trigger breakdown event
                    Misc.Breakdown(v, c);
                }
            }

            // execute the deferred kills
            foreach (ProtoCrewMember c in deferred_kills)
            {
                Misc.Kill(v, c);
            }
        }
Esempio n. 5
0
        public void Execute(Vessel v, Vessel_info vi, Vessel_resources resources, double elapsed_s)
        {
            // store list of crew to kill
            List <ProtoCrewMember> deferred_kills = new List <ProtoCrewMember>();

            // get input resource handler
            Resource_info res = input.Length > 0 ? resources.Info(v, input) : null;

            // determine message variant
            uint variant = vi.temperature < Settings.SurvivalTemperature ? 0 : 1u;

            // get product of all environment modifiers
            double k = Modifiers.Evaluate(v, vi, resources, modifiers);

            // for each crew
            foreach (ProtoCrewMember c in Lib.CrewList(v))
            {
                // get kerbal data
                KerbalData kd = DB.Kerbal(c.name);

                // skip rescue kerbals
                if (kd.rescue)
                {
                    continue;
                }

                // skip disabled kerbals
                if (kd.disabled)
                {
                    continue;
                }

                // get kerbal property data from db
                RuleData rd = kd.Rule(name);

                // if continuous
                double step;
                if (interval <= double.Epsilon)
                {
                    // influence consumption by elapsed time
                    step = elapsed_s;
                }
                // if interval-based
                else
                {
                    // accumulate time
                    rd.time_since += elapsed_s;

                    // determine number of steps
                    step = Math.Floor(rd.time_since / interval);

                    // consume time
                    rd.time_since -= step * interval;

                    // remember if a meal is consumed/produced in this simulation step
                    res.meal_happened |= step > 0.99;
                    if (output.Length > 0)
                    {
                        ResourceCache.Info(v, output).meal_happened |= step > 0.99;
                    }
                }

                // if continuous, or if one or more intervals elapsed
                if (step > double.Epsilon)
                {
                    // if there is a resource specified
                    if (res != null && rate > double.Epsilon)
                    {
                        // determine amount of resource to consume
                        double required = rate                                // consumption rate
                                          * k                                 // product of environment modifiers
                                          * step;                             // seconds elapsed or number of steps

                        // if there is no output
                        if (output.Length == 0)
                        {
                            // simply consume (that is faster)
                            res.Consume(required);
                        }
                        // if there is an output and monitor is false
                        else if (!monitor)
                        {
                            // transform input into output resource
                            // - rules always dump excess overboard (because it is waste)
                            Resource_recipe recipe = new Resource_recipe();
                            recipe.Input(input, required);
                            recipe.Output(output, required * ratio, true);
                            resources.Transform(recipe);
                        }
                        // if monitor then do not consume input resource and only produce output if resource percentage + monitor_offset is < 100%
                        else if ((res.amount / res.capacity) + monitor_offset < 1.0)
                        {
                            // simply produce (that is faster)
                            resources.Produce(v, output, required * ratio);
                        }
                    }

                    // degenerate:
                    // - if the environment modifier is not telling to reset (by being zero)
                    // - if the input threshold is reached if used
                    // - if this rule is resource-less, or if there was not enough resource in the vessel
                    if (input_threshold >= double.Epsilon)
                    {
                        if (res.amount >= double.Epsilon && res.capacity >= double.Epsilon)
                        {
                            trigger = (res.amount / res.capacity) + monitor_offset >= input_threshold;
                        }
                        else
                        {
                            trigger = false;
                        }
                    }
                    else
                    {
                        trigger = input.Length == 0 || res.amount <= double.Epsilon;
                    }

                    if (k > 0.0 && trigger)
                    {
                        rd.problem += degeneration                                   // degeneration rate per-second or per-interval
                                      * k                                            // product of environment modifiers
                                      * step                                         // seconds elapsed or by number of steps
                                      * Variance(c, variance);                       // kerbal-specific variance
                    }
                    // else slowly recover
                    else
                    {
                        rd.problem *= 1.0 / (1.0 + Math.Max(interval, 1.0) * step * 0.002);
                        rd.problem  = Math.Max(rd.problem, 0.0);
                    }
                }

                // kill kerbal if necessary
                if (rd.problem >= fatal_threshold)
                {
                    if (fatal_message.Length > 0)
                    {
                        Message.Post(breakdown ? Severity.breakdown : Severity.fatality, Lib.ExpandMsg(fatal_message, v, c, variant));
                    }

                    if (breakdown)
                    {
                        // trigger breakdown event
                        Misc.Breakdown(v, c);

                        // move back between warning and danger level
                        rd.problem = (warning_threshold + danger_threshold) * 0.5;

                        // make sure next danger message is shown
                        rd.message = 1;
                    }
                    else
                    {
                        deferred_kills.Add(c);
                    }
                }
                // show messages
                else if (rd.problem >= danger_threshold && rd.message < 2)
                {
                    if (danger_message.Length > 0)
                    {
                        Message.Post(Severity.danger, Lib.ExpandMsg(danger_message, v, c, variant));
                    }
                    rd.message = 2;
                }
                else if (rd.problem >= warning_threshold && rd.message < 1)
                {
                    if (warning_message.Length > 0)
                    {
                        Message.Post(Severity.warning, Lib.ExpandMsg(warning_message, v, c, variant));
                    }
                    rd.message = 1;
                }
                else if (rd.problem < warning_threshold && rd.message > 0)
                {
                    if (relax_message.Length > 0)
                    {
                        Message.Post(Severity.relax, Lib.ExpandMsg(relax_message, v, c, variant));
                    }
                    rd.message = 0;
                }
            }

            // execute the deferred kills
            foreach (ProtoCrewMember c in deferred_kills)
            {
                Misc.Kill(v, c);
            }
        }
Esempio n. 6
0
        void FixedUpdate()
        {
            // remove control locks in any case
            Misc.ClearLocks();

            // do nothing if paused
            if (Lib.IsPaused())
            {
                return;
            }

            // convert elapsed time to double only once
            double fixedDeltaTime = TimeWarp.fixedDeltaTime;

            // and detect warp blending
            if (Math.Abs(fixedDeltaTime - elapsed_s) < 0.001)
            {
                warp_blending = 0;
            }
            else
            {
                ++warp_blending;
            }

            // update elapsed time
            elapsed_s = fixedDeltaTime;

            // store info for oldest unloaded vessel
            double          last_time      = 0.0;
            Guid            last_id        = Guid.Empty;
            Vessel          last_v         = null;
            VesselData      last_vd        = null;
            VesselResources last_resources = null;

            foreach (VesselData vd in DB.VesselDatas)
            {
                vd.EarlyUpdate();
            }

            // for each vessel
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // get vessel data
                VesselData vd = v.KerbalismData();

                // update the vessel data validity
                vd.Update(v);

                // set locks for active vessel
                if (v.isActiveVessel)
                {
                    Misc.SetLocks(v);
                }

                // maintain eva dead animation and helmet state
                if (v.loaded && v.isEVA)
                {
                    EVA.Update(v);
                }

                // keep track of rescue mission kerbals, and gift resources to their vessels on discovery
                if (v.loaded && vd.is_vessel)
                {
                    // manage rescue mission mechanics
                    Misc.ManageRescueMission(v);
                }

                // do nothing else for invalid vessels
                if (!vd.IsSimulated)
                {
                    continue;
                }

                // get resource cache
                VesselResources resources = ResourceCache.Get(v);

                // if loaded
                if (v.loaded)
                {
                    //UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.VesselDataEval");
                    // update the vessel info
                    vd.Evaluate(false, elapsed_s);
                    //UnityEngine.Profiling.Profiler.EndSample();

                    // get most used resource
                    ResourceInfo ec = resources.GetResource(v, "ElectricCharge");

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Radiation");
                    // show belt warnings
                    Radiation.BeltWarnings(v, vd);

                    // update storm data
                    Storm.Update(v, vd, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Comms");
                    Communications.Update(v, vd, ec, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    // Habitat equalization
                    ResourceBalance.Equalizer(v);

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Science");
                    // transmit science data
                    Science.Update(v, vd, ec, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Profile");
                    // apply rules
                    Profile.Execute(v, vd, resources, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Profile");
                    // part module resource updates
                    vd.ResourceUpdate(resources, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Resource");
                    // apply deferred requests
                    resources.Sync(v, vd, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    // call automation scripts
                    vd.computer.Automate(v, vd, resources);

                    // remove from unloaded data container
                    unloaded.Remove(vd.VesselId);
                }
                // if unloaded
                else
                {
                    // get unloaded data, or create an empty one
                    Unloaded_data ud;
                    if (!unloaded.TryGetValue(vd.VesselId, out ud))
                    {
                        ud = new Unloaded_data();
                        unloaded.Add(vd.VesselId, ud);
                    }

                    // accumulate time
                    ud.time += elapsed_s;

                    // maintain oldest entry
                    if (ud.time > last_time)
                    {
                        last_time      = ud.time;
                        last_v         = v;
                        last_vd        = vd;
                        last_resources = resources;
                    }
                }
            }

            // at most one vessel gets background processing per physics tick :
            // if there is a vessel that is not the currently loaded vessel, then
            // we will update the vessel whose most recent background update is the oldest
            if (last_v != null)
            {
                //UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.VesselDataEval");
                // update the vessel info (high timewarp speeds reevaluation)
                last_vd.Evaluate(false, last_time);
                //UnityEngine.Profiling.Profiler.EndSample();

                // get most used resource
                ResourceInfo last_ec = last_resources.GetResource(last_v, "ElectricCharge");

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Radiation");
                // show belt warnings
                Radiation.BeltWarnings(last_v, last_vd);

                // update storm data
                Storm.Update(last_v, last_vd, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Comms");
                Communications.Update(last_v, last_vd, last_ec, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Profile");
                // apply rules
                Profile.Execute(last_v, last_vd, last_resources, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Background");
                // simulate modules in background
                Background.Update(last_v, last_vd, last_resources, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Science");
                // transmit science	data
                Science.Update(last_v, last_vd, last_ec, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Resource");
                // apply deferred requests
                last_resources.Sync(last_v, last_vd, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                // call automation scripts
                last_vd.computer.Automate(last_v, last_vd, last_resources);

                // remove from unloaded data container
                unloaded.Remove(last_vd.VesselId);
            }

            // update storm data for one body per-step
            if (storm_bodies.Count > 0)
            {
                storm_bodies.ForEach(k => k.time += elapsed_s);
                Storm_data sd = storm_bodies[storm_index];
                Storm.Update(sd.body, sd.time);
                sd.time     = 0.0;
                storm_index = (storm_index + 1) % storm_bodies.Count;
            }
        }
Esempio n. 7
0
        public override void OnLoad(ConfigNode node)
        {
            // everything in there will be called only one time : the first time a game is loaded from the main menu
            if (!IsCoreGameInitDone)
            {
                try
                {
                    // core game systems
                    Sim.Init();                             // find suns (Kopernicus support)
                    Radiation.Init();                       // create the radiation fields
                    ScienceDB.Init();                       // build the science database (needs Sim.Init() and Radiation.Init() first)
                    Science.Init();                         // register the science hijacker

                    // static graphic components
                    LineRenderer.Init();
                    ParticleRenderer.Init();
                    Highlighter.Init();

                    // UI
                    Textures.Init();                                          // set up the icon textures
                    UI.Init();                                                // message system, main gui, launcher
                    KsmGui.KsmGuiMasterController.Init();                     // setup the new gui framework

                    // part prefabs hacks
                    Profile.SetupPods();                     // add supply resources to pods
                    Misc.PartPrefabsTweaks();                // part prefabs tweaks, must be called after ScienceDB.Init()

                    // Create KsmGui windows
                    new ScienceArchiveWindow();

                    // GameEvents callbacks
                    Callbacks = new Callbacks();
                }
                catch (Exception e)
                {
                    string fatalError = "FATAL ERROR : Kerbalism core init has failed :" + "\n" + e.ToString();
                    Lib.Log(fatalError, Lib.LogLevel.Error);
                    LoadFailedPopup(fatalError);
                }

                IsCoreGameInitDone = true;
            }

            // everything in there will be called every time a savegame (or a new game) is loaded from the main menu
            if (!IsSaveGameInitDone)
            {
                try
                {
                    Cache.Init();
                    ResourceCache.Init();

                    // prepare storm data
                    foreach (CelestialBody body in FlightGlobals.Bodies)
                    {
                        if (Storm.Skip_body(body))
                        {
                            continue;
                        }
                        Storm_data sd = new Storm_data {
                            body = body
                        };
                        storm_bodies.Add(sd);
                    }
                }
                catch (Exception e)
                {
                    string fatalError = "FATAL ERROR : Kerbalism save game init has failed :" + "\n" + e.ToString();
                    Lib.Log(fatalError, Lib.LogLevel.Error);
                    LoadFailedPopup(fatalError);
                }

                IsSaveGameInitDone = true;
            }

            // eveything else will be called on every OnLoad() call :
            // - save/load
            // - every scene change
            // - in various semi-random situations (thanks KSP)

            // Fix for background IMGUI textures being dropped on scene changes since KSP 1.8
            Styles.ReloadBackgroundStyles();

            // always clear the caches
            Cache.Clear();
            ResourceCache.Clear();

            // deserialize our database
            try
            {
                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.DB.Load");
                DB.Load(node);
                UnityEngine.Profiling.Profiler.EndSample();
            }
            catch (Exception e)
            {
                string fatalError = "FATAL ERROR : Kerbalism save game load has failed :" + "\n" + e.ToString();
                Lib.Log(fatalError, Lib.LogLevel.Error);
                LoadFailedPopup(fatalError);
            }

            // I'm smelling the hacky mess in here.
            Communications.NetworkInitialized  = false;
            Communications.NetworkInitializing = false;

            // detect if this is a different savegame
            if (DB.uid != savegame_uid)
            {
                // clear caches
                Message.all_logs.Clear();

                // sync main window pos from db
                UI.Sync();

                // remember savegame id
                savegame_uid = DB.uid;
            }

            Kerbalism.gameLoadTime = Time.time;
        }
        // ctor
        public Vessel_Info(Vessel v, uint vessel_id, UInt64 inc)
        {
            // NOTE: anything used here can't in turn use cache, unless you know what you are doing

            // NOTE: you can't cache vessel position
            //  at any point in time all vessel/body positions are relative to a different frame of reference
            //  so comparing the current position of a vessel, with the cached one of another make no sense

            // associate with an unique incremental id
            this.inc = inc;

            // determine if this is a valid vessel
            is_vessel = Lib.IsVessel(v);

            if (!is_vessel)
            {
                return;
            }

            // determine if this is a rescue mission vessel
            is_rescue = Misc.IsRescueMission(v);
            if (is_rescue)
            {
                return;
            }

            // dead EVA are not valid vessels
            if (EVA.IsDead(v))
            {
                return;
            }

            // shortcut for common tests
            is_valid = true;

            // generate id once
            id = vessel_id;

            // calculate crew info for the vessel
            crew_count    = Lib.CrewCount(v);
            crew_capacity = Lib.CrewCapacity(v);

            // get vessel position
            Vector3d position = Lib.VesselPosition(v);

            // this should never happen again
            if (Vector3d.Distance(position, v.mainBody.position) < 1.0)
            {
                throw new Exception("Shit hit the fan for vessel " + v.vesselName);
            }

            // determine if in sunlight, calculate sun direction and distance
            sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0;

            // at the two highest timewarp speed, the number of sun visibility samples drop to the point that
            // the quantization error first became noticeable, and then exceed 100%
            // to solve this, we switch to an analytical estimation of the portion of orbit that was in sunlight
            // - we check against timewarp rate, instead of index, to avoid issues during timewarp blending
            if (v.mainBody.flightGlobalsIndex != 0 && TimeWarp.CurrentRate > 1000.0f)
            {
                sunlight = 1.0 - Sim.ShadowPeriod(v) / Sim.OrbitalPeriod(v);
            }

            // environment stuff
            atmo_factor        = Sim.AtmosphereFactor(v.mainBody, position, sun_dir);
            gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude);
            underwater         = Sim.Underwater(v);
            breathable         = Sim.Breathable(v, underwater);
            landed             = Lib.Landed(v);

            // temperature at vessel position
            temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux);
            temp_diff   = Sim.TempDiff(temperature, v.mainBody, landed);

            // radiation
            radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out magnetosphere, out inner_belt, out outer_belt, out interstellar);

            // extended atmosphere
            thermosphere = Sim.InsideThermosphere(v);
            exosphere    = Sim.InsideExosphere(v);

            // malfunction stuff
            malfunction = Reliability.HasMalfunction(v);
            critical    = Reliability.HasCriticalFailure(v);

            // signal info
            if (Features.KCommNet)
            {
                antenna = Cache.AntennaInfo(v);
                avoid_inf_recursion.Add(v.id);
            }
            else
            {
                kAntenna = new KAntennaInfo(v);
                avoid_inf_recursion.Add(v.id);
            }
            // TODO: Need to create a Signal integrated with CommNet
            connection   = Signal.Connection(v, position, kAntenna, blackout, avoid_inf_recursion);
            transmitting = Science.Transmitting(v, connection.linked);
            relaying     = Signal.Relaying(v, avoid_inf_recursion);
            avoid_inf_recursion.Remove(v.id);

            // habitat data
            volume       = Habitat.Total_Volume(v);
            surface      = Habitat.Total_Surface(v);
            pressure     = Habitat.Pressure(v);
            poisoning    = Habitat.Poisoning(v);
            shielding    = Habitat.Shielding(v);
            living_space = Habitat.Living_Space(v);
            comforts     = new Comforts(v, landed, crew_count > 1, true); // TODO: replace 'true' for connection.linked

            // data about greenhouses
            greenhouses = Greenhouse.Greenhouses(v);

            // other stuff
            gravioli = Sim.Graviolis(v);
        }