예제 #1
0
        public link_data ComputeLink(Vessel v, HashSet <Guid> avoid_inf_recursion)
        {
            // if it has no antenna
            if (antennas[v.id].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(v))
            {
                return(new link_data(false, link_status.no_link, 0.0));
            }

            // check for direct link
            // note: we also get distance from the cache and store it in the link
            double direct_visible_dist = direct_visibility_cache[v.id];
            bool   direct_visible      = direct_visible_dist > 0.0;

            if (direct_visible)
            {
                return(new link_data(true, link_status.direct_link, direct_visible_dist));
            }

            // avoid infinite recursion
            avoid_inf_recursion.Add(v.id);

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

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

                // avoid infinite recursion
                if (avoid_inf_recursion.Contains(w.id))
                {
                    continue;
                }

                // avoid testing against itself
                if (v == w)
                {
                    continue;
                }

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

                // check for indirect link to home body
                // note: we also get distance from the cache
                // note: we check the relay range, that is asymmetric
                double indirect_visible_dist = indirect_visibility_cache[Lib.CombineGuid(v.id, w.id)];
                bool   indirect_visible      = indirect_visible_dist > 0.0 && indirect_visible_dist < Math.Min(v_ad.range, w_ad.relay_range);
                if (indirect_visible)
                {
                    // check link to home body, recursively
                    link_data next_link = ComputeLink(w, avoid_inf_recursion);

                    // if indirectly linked
                    if (next_link.linked)
                    {
                        // flag the relay for ec consumption, but only once
                        if (!active_relays.ContainsKey(w.id))
                        {
                            active_relays.Add(w.id, w_ad.relay_cost);
                        }

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

            // no link
            return(new link_data(false, link_status.no_link, 0.0));
        }
예제 #2
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));
        }
예제 #3
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);
                }
            }
        }
예제 #4
0
파일: Cache.cs 프로젝트: zajc3w/Kerbalism
  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);
  }