Beispiel #1
0
 // calculate a cache entry for the vessel
 static vessel_info Compute(Vessel v)
 {
   vessel_info info = new vessel_info();
   info.position = Lib.VesselPosition(v);
   info.sunlight = Sim.RaytraceBody(v, Sim.Sun(), out info.sun_dir, out info.sun_dist);
   info.temperature = Sim.Temperature(v, info.sunlight);
   info.cosmic_radiation = Radiation.CosmicRadiation(v);
   info.belt_radiation = Radiation.BeltRadiation(v);
   info.storm_radiation = Radiation.StormRadiation(v, info.sunlight);
   info.env_radiation = info.cosmic_radiation + info.belt_radiation + info.storm_radiation;
   info.breathable = Sim.Breathable(v);
   foreach(var p in Kerbalism.rules)
   {
     Rule r = p.Value;
     if (r.resource_name.Length > 0)
     {
       var vmon = new vmon_cache();
       vmon.depletion = r.EstimateLifetime(v);
       double amount = Lib.GetResourceAmount(v, r.resource_name);
       double capacity = Lib.GetResourceCapacity(v, r.resource_name);
       vmon.level = capacity > double.Epsilon ? amount / capacity : 1.0; //< level is 1 with no capacity
       info.vmon.Add(p.Value.name, vmon);
     }
   }
   return info;
 }
Beispiel #2
0
  // get vessel info from the cache, or compute a new one and add it to the cache
  public static vessel_info VesselInfo(Vessel v)
  {
    // get the info from the cache, if it exist
    vessel_info info;
    if (instance.vessels.TryGetValue(v.id, out info)) return info;

    // compute vessel info
    info = new vessel_info();
    info.position = Lib.VesselPosition(v);
    info.sunlight = Sim.RaytraceBody(v, Sim.Sun(), out info.sun_dir, out info.sun_dist);
    info.temperature = Sim.Temperature(v, info.sunlight);
    info.cosmic_radiation = Radiation.CosmicRadiation(v);
    info.belt_radiation = Radiation.BeltRadiation(v);
    info.storm_radiation = Radiation.StormRadiation(v, info.sunlight);
    info.radiation = (info.cosmic_radiation + info.belt_radiation + info.storm_radiation) * (1.0 - Radiation.Shielding(v));

    // store vessel info in the cache
    instance.vessels.Add(v.id, info);

    // return the vessel info
    return info;
  }
Beispiel #3
0
        public Vessel_info(Vessel v, UInt64 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);
            evas            = (uint)(Math.Max(0, ResourceCache.Info(v, "Nitrogen").amount - 330) / PreferencesLifeSupport.Instance.evaAtmoLoss);
            poisoning       = Habitat.Poisoning(v);
            humidity        = Habitat.Humidity(v);
            shielding       = Habitat.Shielding(v);
            living_space    = Habitat.Living_space(v);
            volume_per_crew = Habitat.Volume_per_crew(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);
        }
Beispiel #4
0
        // build the visibility caches
        void BuildVisibility()
        {
            // get home body
            CelestialBody home = FlightGlobals.GetHomeBody();

            // build direct visibility cache
            direct_visibility_cache.Clear();
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // skip invalid vessels
                if (!Lib.IsVessel(v))
                {
                    continue;
                }

                // get antenna data
                antenna_data ad = antennas[v.id];

                // raytrace home body
                Vector3d dir;
                double   dist    = 0.0;
                bool     visible = Sim.RaytraceBody(v, home, out dir, out dist);
                dist = Math.Abs(dist); //< avoid problem below water level

                // store in visibility cache
                // note: we store distance & visibility flag at the same time
                direct_visibility_cache.Add(v.id, visible && dist < ad.range ? dist : 0.0);
            }


            // build indirect visibility cache
            indirect_visibility_cache.Clear();
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // skip invalid vessels
                if (!Lib.IsVessel(v))
                {
                    continue;
                }

                // get antenna data
                antenna_data v_ad = antennas[v.id];

                // for each vessel
                foreach (Vessel w in FlightGlobals.Vessels)
                {
                    // skip invalid vessels
                    if (!Lib.IsVessel(w))
                    {
                        continue;
                    }

                    // do not test with itself
                    if (v == w)
                    {
                        continue;
                    }

                    // do not compute visibility when both vessels have a direct link
                    // rationale: optimization, the indirect visibility it never used in this case
                    if (direct_visibility_cache[v.id] > double.Epsilon && direct_visibility_cache[w.id] > double.Epsilon)
                    {
                        continue;
                    }

                    // generate merged guid
                    Guid id = Lib.CombineGuid(v.id, w.id);

                    // avoid raycasting the same pair twice
                    if (indirect_visibility_cache.ContainsKey(id))
                    {
                        continue;
                    }

                    // get antenna data
                    antenna_data w_ad = antennas[w.id];

                    // raytrace the vessel
                    Vector3d dir;
                    double   dist    = 0.0;
                    bool     visible = Sim.RaytraceVessel(v, w, out dir, out dist);

                    // store visibility in cache
                    // note: we store distance & visibility flag at the same time
                    // note: relay visibility is asymmetric, done at link build time
                    indirect_visibility_cache.Add(id, visible && dist < Math.Min(v_ad.range, w_ad.range) ? dist : 0.0);
                }
            }
        }
Beispiel #5
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 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
    antenna = new AntennaInfo(v);
    avoid_inf_recursion.Add(v.id);
    connection = Signal.connection(v, position, antenna, 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.tot_volume(v);
    surface = Habitat.tot_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, connection.linked);

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

    // other stuff
    gravioli = Sim.Graviolis(v);
  }
Beispiel #6
0
        public static link_data Link(Vessel v, Vector3d position, antenna_data antenna, bool blackout, HashSet <Guid> avoid_inf_recursion)
        {
            // assume linked if signal mechanic is disabled
            if (!Kerbalism.features.signal)
            {
                return(new link_data(true, link_status.direct_link, double.MaxValue));
            }

            // if it has no antenna
            if (antenna.range <= double.Epsilon)
            {
                return(new link_data(false, link_status.no_antenna, 0.0));
            }

            // if there is a storm and the vessel is inside a magnetosphere
            if (blackout)
            {
                return(new link_data(false, link_status.no_link, 0.0));
            }

            // store raytracing data
            Vector3d dir;
            double   dist;
            bool     visible;

            // raytrace home body
            visible = Sim.RaytraceBody(v, position, FlightGlobals.GetHomeBody(), out dir, out dist);
            dist    = visible && antenna.range > dist ? dist : double.MaxValue;

            // if directly linked
            if (antenna.range > dist)
            {
                return(new link_data(true, link_status.direct_link, dist));
            }

            // for each other vessel
            foreach (Vessel w in FlightGlobals.Vessels)
            {
                // do not test with itself
                if (v == w)
                {
                    continue;
                }

                // skip vessels already in this chain
                if (avoid_inf_recursion.Contains(w.id))
                {
                    continue;
                }

                // get vessel from the cache
                // note: safe because we are avoiding infinite recursion
                vessel_info wi = Cache.VesselInfo(w);

                // skip invalid vessels
                if (!wi.is_valid)
                {
                    continue;
                }

                // skip non-relays and non-linked relays
                if (wi.antenna.relay_range <= double.Epsilon || !wi.link.linked)
                {
                    continue;
                }

                // raytrace the other vessel
                visible = Sim.RaytraceVessel(v, w, position, wi.position, out dir, out dist);
                dist    = visible && antenna.range > dist ? dist : double.MaxValue;

                // if indirectly linked
                // note: relays with no EC have zero relay_range
                // note: avoid relay loops
                if (antenna.range > dist && wi.antenna.relay_range > dist && !wi.link.path.Contains(v))
                {
                    // create indirect link data
                    link_data link = new link_data(wi.link);

                    // update the link data and return it
                    link.status   = link_status.indirect_link;
                    link.distance = dist; //< store distance of last link
                    link.path.Add(w);
                    return(link);
                }
            }

            // no link
            return(new link_data(false, link_status.no_link, 0.0));
        }
Beispiel #7
0
        public static ConnectionInfo connection(Vessel v, Vector3d position, AntennaInfo antenna, bool blackout, HashSet <Guid> avoid_inf_recursion)
        {
            // if signal mechanic is disabled, use RemoteTech/CommNet/S4
            if (!Features.Signal)
            {
                return(OtherComms(v));
            }

            // if it has no antenna
            if (antenna.no_antenna)
            {
                return(new ConnectionInfo(LinkStatus.no_antenna));
            }

            // if there is a storm and the vessel is inside a magnetosphere
            if (blackout)
            {
                return(new ConnectionInfo(LinkStatus.blackout));
            }

            // store raytracing data
            Vector3d dir;
            double   dist;
            bool     visible;

            // store other data
            double rate;
            List <ConnectionInfo> connections = new List <ConnectionInfo>();

            // raytrace home body
            visible = Sim.RaytraceBody(v, position, FlightGlobals.GetHomeBody(), out dir, out dist);

            // get rate
            rate = antenna.direct_rate(dist);

            // if directly linked
            if (visible && rate > Settings.ControlRate)
            {
                ConnectionInfo conn = new ConnectionInfo(LinkStatus.direct_link, rate, antenna.direct_cost);
                connections.Add(conn);
            }

            // for each other vessel
            foreach (Vessel w in FlightGlobals.Vessels)
            {
                // do not test with itself
                if (v == w)
                {
                    continue;
                }

                // skip vessels already in this chain
                if (avoid_inf_recursion.Contains(w.id))
                {
                    continue;
                }

                // get vessel from the cache
                // - when:
                //   . cache is empty (eg: new savegame loaded)
                // - we avoid single-tick wrong paths arising from this situation:
                //   . vessel A is directly linked
                //   . vessel B is indirectly linked through A
                //   . cache is cleared (after loading a savegame)
                //   . cache of A is computed
                //   . in turn, cache of B is computed ignoring A (and stored)
                //   . until cache of B is re-computed, B will result incorrectly not linked
                // - in this way:
                //   . cache of A is computed
                //   . in turn, cache of B is computed ignoring A (but not stored)
                //   . cache of B is then computed correctly
                //   . do not degenerate into O(N^3) by using non-optimal path
                vessel_info wi;
                if (!Cache.HasVesselInfo(w, out wi))
                {
                    if (connections.Count > 0)
                    {
                        continue;
                    }
                    else
                    {
                        wi = new vessel_info(w, Lib.VesselID(w), 0);
                    }
                }

                // skip invalid vessels
                if (!wi.is_valid)
                {
                    continue;
                }

                // skip non-relays and non-linked relays
                if (!wi.antenna.is_relay || !wi.connection.linked)
                {
                    continue;
                }

                // raytrace the other vessel
                visible = Sim.RaytraceVessel(v, w, position, Lib.VesselPosition(w), out dir, out dist);

                // get rate
                rate = antenna.indirect_rate(dist, wi.antenna);

                // if indirectly linked
                // - relays with no EC have zero relay_range
                // - avoid relay loops
                if (visible && rate > Settings.ControlRate && !wi.connection.path.Contains(v))
                {
                    // create indirect link data
                    ConnectionInfo conn = new ConnectionInfo(wi.connection);

                    // update the link data and return it
                    conn.status = LinkStatus.indirect_link;
                    conn.rate   = Math.Min(conn.rate, rate);
                    conn.cost   = antenna.indirect_cost;
                    conn.path.Add(w);
                    connections.Add(conn);
                }
            }

            // if at least a connection has been found
            if (connections.Count > 0)
            {
                // select the best connection
                double best_rate  = 0.0;
                int    best_index = 0;
                for (int i = 0; i < connections.Count; ++i)
                {
                    if (connections[i].rate > best_rate)
                    {
                        best_rate  = connections[i].rate;
                        best_index = i;
                    }
                }

                // and return it
                return(connections[best_index]);
            }

            // no link
            return(new ConnectionInfo(LinkStatus.no_link));
        }
Beispiel #8
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

    // 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 resque mission vessel
    is_resque = Lib.IsResqueMission(v);
    if (is_resque) return;

    // dead EVA are not valid vessels
    if (v.isEVA && EVA.KerbalData(v).eva_dead) 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 once
    position = Lib.VesselPosition(v);

    // 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;

    // if the orbit length vs simulation step is lower than an acceptable threshold, use discrete sun visibility
    if (v.mainBody.flightGlobalsIndex != 0)
    {
      double orbit_period = Sim.OrbitalPeriod(v);
      if (orbit_period / Kerbalism.elapsed_s < 16.0) sunlight = 1.0 - Sim.ShadowPeriod(v) / orbit_period;
    }

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

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

    // calculate radiation
    radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out inside_pause, out inside_belt);

    // calculate malfunction stuff
    max_malfunction = Reliability.MaxMalfunction(v);
    avg_quality = Reliability.AverageQuality(v);

    // calculate signal info
    antenna = new antenna_data(v);
    avoid_inf_recursion.Add(v.id);
    link = Signal.Link(v, position, antenna, blackout, avoid_inf_recursion);
    avoid_inf_recursion.Remove(v.id);

    // partial data about modules, used by vessel info/monitor
    scrubbers = Scrubber.PartialData(v);
    recyclers = Recycler.PartialData(v);
    greenhouses = Greenhouse.PartialData(v);

    // woot relativity
    time_dilation = Sim.TimeDilation(v);
  }