public SCANdata getData(CelestialBody body) { SCANdata data = getData(body.bodyName); data.body = body; return(data); }
/// <summary> /// Determines scanning coverage for a given area with a given scanner type /// </summary> /// <param name="lon">Clamped double in the -180 - 180 degree range</param> /// <param name="lat">Clamped double in the -90 - 90 degree range</param> /// <param name="body">Celestial body in question</param> /// <param name="SCANtype">SCANtype cast as an integer</param> /// <returns></returns> public static bool isCovered(double lon, double lat, CelestialBody body, int SCANtype) { int ilon = icLON(lon); int ilat = icLAT(lat); if (badLonLat(ilon, ilat)) { return(false); } if (SCANcontroller.controller != null) { SCANdata data = getData(body); if (data != null) { return((data.Coverage[ilon, ilat] & SCANtype) != 0); } else { return(false); } } else { return(false); } }
internal static bool isCoveredByAll(int lon, int lat, SCANdata data, SCANtype type) { if (badLonLat(lon, lat)) { return(false); } return((data.Coverage[lon, lat] & (Int32)type) == (Int32)type); }
public SCANdata getData(string name) { if (!body_data.ContainsKey(name)) { body_data[name] = new SCANdata(); body_data[name].resetImages(); } return(body_data[name]); }
/// <summary> /// Determines scanning coverage for a given area with a given scanner type /// </summary> /// <param name="lon">Clamped integer in the 0-360 degree range</param> /// <param name="lat">Clamped integer in the 0-180 degree range</param> /// <param name="body">Celestial body in question</param> /// <param name="SCANtype">SCANtype cast as an integer</param> /// <returns></returns> public static bool isCovered(int lon, int lat, CelestialBody body, int SCANtype) { if (badLonLat(lon, lat)) { return(false); } SCANdata data = getData(body); return((data.coverage[lon, lat] & SCANtype) != 0); }
internal static SCANdata getData(CelestialBody body) { if (!SCANcontroller.body_data.ContainsKey(body.name)) { SCANcontroller.body_data[body.name] = new SCANdata(body); } SCANdata data = SCANcontroller.body_data[body.name]; return(data); }
internal static bool isCovered(double lon, double lat, SCANdata data, SCANtype type) { int ilon = icLON(lon); int ilat = icLAT(lat); if (badLonLat(ilon, ilat)) { return(false); } return((data.Coverage[ilon, ilat] & (Int32)type) != 0); }
internal static void registerPass(double lon, double lat, SCANdata data, SCANtype type) { int ilon = SCANUtil.icLON(lon); int ilat = SCANUtil.icLAT(lat); if (SCANUtil.badLonLat(ilon, ilat)) { return; } data.Coverage[ilon, ilat] |= (Int32)type; }
public void scanFromAllVessels() { if (Time.realtimeSinceStartup - last_scan_time < 1 && Time.realtimeSinceStartup > last_scan_time) { return; } if (last_scan_frame == Time.frameCount) { return; } last_scan_frame = Time.frameCount; last_scan_time = Time.realtimeSinceStartup; scan_UT = Planetarium.GetUniversalTime(); currentActiveSensor = 0; currentActiveVessel = 0; actualPasses = 0; maxRes = 0; foreach (SCANdata data in body_data.Values) { data.updateCoverage(); } foreach (Vessel v in FlightGlobals.Vessels) { if (!knownVessels.ContainsKey(v.id)) { continue; } SCANvessel vessel = knownVessels[v.id]; SCANdata data = getData(v.mainBody); vessel.vessel = v; if (!data.disabled) { if (v.mainBody == FlightGlobals.currentMainBody || scan_background) { if (isVesselKnown(v)) { doScanPass(knownVessels[v.id], scan_UT, scan_UT, vessel.lastUT, vessel.latitude, vessel.longitude); ++currentActiveVessel; currentActiveSensor += knownVessels[v.id].sensors.Count; } } } vessel.body = v.mainBody; vessel.frame = Time.frameCount; vessel.lastUT = scan_UT; vessel.latitude = fixLatitude(v.latitude); vessel.longitude = fixLongitude(v.longitude); } activeVessels = currentActiveVessel; activeSensors = currentActiveSensor; }
/// <summary> /// Determines scanning coverage for a given area with a given scanner type /// </summary> /// <param name="lon">Clamped double in the -180 - 180 degree range</param> /// <param name="lat">Clamped double in the -90 - 90 degree range</param> /// <param name="body">Celestial body in question</param> /// <param name="SCANtype">SCANtype cast as an integer</param> /// <returns></returns> public static bool isCovered(double lon, double lat, CelestialBody body, int SCANtype) { int ilon = icLON(lon); int ilat = icLAT(lat); if (badLonLat(ilon, ilat)) { return(false); } SCANdata data = getData(body); return((data.coverage[ilon, ilat] & SCANtype) != 0); }
/* SCAN: add static (a warning that we're low on electric charge) */ public void addStatic() { SCANdata data = SCANUtil.getData(vessel.mainBody); Texture2D map = data.map_small; if (map != null) { for (int i = 0; i < 1000; ++i) { map.SetPixel(UnityEngine.Random.Range(0, 360), UnityEngine.Random.Range(0, 180), Color.Lerp(Color.black, Color.white, UnityEngine.Random.value)); } } }
public override void OnLoad(ConfigNode node) { ConfigNode node_vessels = node.GetNode("Scanners"); if (node_vessels != null) { print("SCANsat Controller: Loading " + node_vessels.CountNodes.ToString() + " known vessels"); foreach (ConfigNode node_vessel in node_vessels.GetNodes("Vessel")) { Guid id = new Guid(node_vessel.GetValue("guid")); string stext = node_vessel.GetValue("sensors"); if (stext != null && stext != "") { int sensors = Convert.ToInt32(stext); if (sensors != 0) { registerSensor(id, (SCANdata.SCANtype)sensors, 0, 0, 0, 0); } } foreach (ConfigNode node_sensor in node_vessel.GetNodes("Sensor")) { int sensor = Convert.ToInt32(node_sensor.GetValue("type")); double fov = Convert.ToDouble(node_sensor.GetValue("fov")); double min_alt = Convert.ToDouble(node_sensor.GetValue("min_alt")); double max_alt = Convert.ToDouble(node_sensor.GetValue("max_alt")); double best_alt = Convert.ToDouble(node_sensor.GetValue("best_alt")); registerSensor(id, (SCANdata.SCANtype)sensor, fov, min_alt, max_alt, best_alt); } } } ConfigNode node_progress = node.GetNode("Progress"); if (node_progress != null) { foreach (ConfigNode node_body in node_progress.GetNodes("Body")) { string body_name = node_body.GetValue("Name"); print("SCANsat Controller: Loading map for " + body_name); SCANdata body_data = getData(body_name); try { string mapdata = node_body.GetValue("Map"); body_data.deserialize(mapdata); } catch (Exception e) { print(e.ToString()); print(e.StackTrace); // fail somewhat gracefully; don't make the save unloadable } body_data.disabled = Convert.ToBoolean(node_body.GetValue("Disabled")); } } }
/* SCAN: add static (a warning that we're low on electric charge) */ private void addStatic() { SCANdata data = SCANUtil.getData(vessel.mainBody); if (data == null) { return; } Texture2D map = data.Map; if (map != null) { for (int i = 0; i < 1000; ++i) { map.SetPixel(UnityEngine.Random.Range(0, 360), UnityEngine.Random.Range(0, 180), palette.lerp(palette.black, palette.white, UnityEngine.Random.value)); } } }
/// <summary> /// Public method to return the scanning coverage for a given sensor type on a give body /// </summary> /// <param name="SCANtype">Integer corresponding to the desired SCANtype</param> /// <param name="Body">Desired Celestial Body</param> /// <returns>Scanning percentage as a double from 0-100</returns> public static double GetCoverage(int SCANtype, CelestialBody Body) { if (SCANcontroller.controller != null) { SCANdata data = getData(Body); if (data != null) { return(getCoveragePercentage(data, (SCANtype)SCANtype)); } else { return(0); } } else { return(0); } }
public override void OnSave(ConfigNode node) { ConfigNode node_vessels = new ConfigNode("Scanners"); foreach (Guid id in knownVessels.Keys) { ConfigNode node_vessel = new ConfigNode("Vessel"); node_vessel.AddValue("guid", id.ToString()); if (knownVessels[id].vessel != null) { node_vessel.AddValue("name", knownVessels[id].vessel.vesselName); // not read } foreach (SCANsensor sensor in knownVessels[id].sensors.Values) { ConfigNode node_sensor = new ConfigNode("Sensor"); node_sensor.AddValue("type", (int)sensor.sensor); node_sensor.AddValue("fov", sensor.fov); node_sensor.AddValue("min_alt", sensor.min_alt); node_sensor.AddValue("max_alt", sensor.max_alt); node_sensor.AddValue("best_alt", sensor.best_alt); node_vessel.AddNode(node_sensor); } node_vessels.AddNode(node_vessel); } node.AddNode(node_vessels); ConfigNode node_progress = new ConfigNode("Progress"); foreach (string body_name in body_data.Keys) { ConfigNode node_body = new ConfigNode("Body"); SCANdata body_scan = body_data[body_name]; node_body.AddValue("Name", body_name); node_body.AddValue("Disabled", body_scan.disabled); node_body.AddValue("Map", body_scan.serialize()); node_progress.AddNode(node_body); } node.AddNode(node_progress); }
internal static double getCoveragePercentage(SCANdata data, SCANtype type) { if (data == null) { return(0); } double cov = 0d; if (type == SCANtype.Nothing) { type = SCANtype.AltimetryLoRes | SCANtype.AltimetryHiRes | SCANtype.Biome | SCANtype.Anomaly; } cov = data.getCoverage(type); if (cov <= 0) { cov = 100; } else { cov = Math.Min(99.9d, 100 - cov * 100d / (360d * 180d * countBits((int)type))); } return(cov); }
/// <summary> /// Determines scanning coverage for a given area with a given scanner type /// </summary> /// <param name="lon">Clamped integer in the 0-360 degree range</param> /// <param name="lat">Clamped integer in the 0-180 degree range</param> /// <param name="body">Celestial body in question</param> /// <param name="SCANtype">SCANtype cast as an integer</param> /// <returns></returns> public static bool isCovered(int lon, int lat, CelestialBody body, int SCANtype) { if (badLonLat(lon, lat)) { return(false); } if (SCANcontroller.controller != null) { SCANdata data = getData(body); if (data != null) { return((data.Coverage[lon, lat] & SCANtype) != 0); } else { return(false); } } else { return(false); } }
public SCANdata getData(string name) { if(!body_data.ContainsKey(name)) { body_data[name] = new SCANdata(); body_data[name].resetImages(); } return body_data[name]; }
public ScienceData getAvailableScience(Vessel v, SCANdata.SCANtype sensor, bool notZero) { SCANdata data = getData(v.mainBody); ScienceData sd = null; ScienceExperiment se = null; ScienceSubject su = null; bool found = false; string id = null; double coverage = 0f; if(v.mainBody.pqsController != null) { if(!found && (sensor & SCANdata.SCANtype.AltimetryLoRes) != SCANdata.SCANtype.Nothing) { found = true; id = "SCANsatAltimetryLoRes"; coverage = data.getCoveragePercentage(SCANdata.SCANtype.AltimetryLoRes); } if(!found && (sensor & SCANdata.SCANtype.AltimetryHiRes) != SCANdata.SCANtype.Nothing) { found = true; id = "SCANsatAltimetryHiRes"; coverage = data.getCoveragePercentage(SCANdata.SCANtype.AltimetryHiRes); } } if(v.mainBody.BiomeMap != null) { if(!found && (sensor & SCANdata.SCANtype.Biome) != SCANdata.SCANtype.Nothing) { found = true; id = "SCANsatBiomeAnomaly"; coverage = data.getCoveragePercentage(SCANdata.SCANtype.Biome | SCANdata.SCANtype.Anomaly); } } if(!found) return null; se = ResearchAndDevelopment.GetExperiment(id); if(se == null) return null; su = ResearchAndDevelopment.GetExperimentSubject(se, ExperimentSituations.InSpaceHigh, v.mainBody, "surface"); if(su == null) return null; print("[SCANsat] coverage " + coverage.ToString("F1") + ", science cap " + su.scienceCap.ToString("F1") + ", subject value " + su.subjectValue.ToString("F2") + ", science value " + su.scientificValue.ToString("F2") + ", science " + su.science.ToString("F2")); su.scientificValue = 1; float science = (float)coverage; if(science > 95) science = 100; if(science < 30) science = 0; science = science / 100f; science = Mathf.Max(0, (science * su.scienceCap) - su.science); print("[SCANsat] remaining science: " + science.ToString("F1") + ", base = " + (se.baseValue).ToString("F1")); science /= Mathf.Max(0.1f, su.scientificValue); science /= su.subjectValue; print("[SCANsat] result = " + science.ToString("F2")); if(notZero && science <= 0) science = 0.00001f; sd = new ScienceData(science, 1f, 0f, id, se.experimentTitle + " of " + v.mainBody.theName); sd.subjectID = su.id; return sd; }
/* MAP: build: map to Texture2D */ public Texture2D getPartialMap() { SCANdata data = SCANcontroller.controller.getData(body); Color[] pix; if (map == null) { map = new Texture2D(mapwidth, mapheight, TextureFormat.ARGB32, false); pix = map.GetPixels(); for (int i = 0; i < pix.Length; ++i) { pix [i] = Color.clear; } map.SetPixels(pix); } else if (mapstep >= map.height) { return(map); } if (redline == null || redline.Length != map.width) { redline = new Color[map.width]; for (int i = 0; i < redline.Length; ++i) { redline [i] = Color.red; } } if (mapstep < map.height - 1) { map.SetPixels(0, mapstep + 1, map.width, 1, redline); } if (mapstep <= 0) { mapstep = 0; mapline = new double[map.width]; } pix = map.GetPixels(0, mapstep, map.width, 1); for (int i = 0; i < map.width; i++) { int scheme = 0; double lat = (mapstep * 1.0f / mapscale) - 90f + lat_offset; double lon = (i * 1.0f / mapscale) - 180f + lon_offset; double la = lat, lo = lon; lat = unprojectLatitude(lo, la); lon = unprojectLongitude(lo, la); pix [i] = Color.grey; if (double.IsNaN(lat) || double.IsNaN(lon) || lat < -90 || lat > 90 || lon < -180 || lon > 180) { pix [i] = Color.clear; continue; } if (mapmode == 0) { if (!data.isCovered(lon, lat, SCANdata.SCANtype.Altimetry)) { continue; } if (body.pqsController == null) { pix [i] = Color.Lerp(Color.black, Color.white, UnityEngine.Random.value); //big_heightmap[i, mapstep, SCANcontroller.controller.projection] = 0; continue; } float val = 0f; if (mapType == 0) { val = big_heightmap[i, mapstep, SCANcontroller.controller.projection]; } if (val == 0) { if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes)) { // high resolution gets a coloured pixel for the actual position val = (float)data.getElevation(lon, lat); pix[i] = heightToColor(val, scheme); heightMapArray(val, mapstep, i, mapType); } else { // basic altimetry gets forced greyscale with lower resolution val = (float)data.getElevation(((int)(lon * 5)) / 5, ((int)(lat * 5)) / 5); pix[i] = heightToColor(val, 1); heightMapArray(val, mapstep, i, mapType); } } else if (val != 0) { if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes)) { pix[i] = heightToColor(val, scheme); } else { pix[i] = heightToColor(val, 1); } } /* draw height lines - works, but mostly useless... * int step = (int)(val / 1000); * int step_h = step, step_v = step; * if(i > 0) step_h = (int)(bigline[i - 1] / 1000); * if(bigstep > 0) step_v = (int)(bigline[i] / 1000); * if(step != step_h || step != step_v) { * pix[i] = Color.white; * } */ mapline [i] = val; } else if (mapmode == 1) { if (!data.isCovered(lon, lat, SCANdata.SCANtype.Altimetry)) { continue; } if (body.pqsController == null) { pix [i] = Color.Lerp(Color.black, Color.white, UnityEngine.Random.value); continue; } float val = 0f; if (mapType == 0) { val = big_heightmap[i, mapstep, SCANcontroller.controller.projection]; } if (val == 0) { if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes)) { val = (float)data.getElevation(lon, lat); heightMapArray(val, mapstep, i, mapType); } else { val = (float)data.getElevation(((int)(lon * 5)) / 5, ((int)(lat * 5)) / 5); heightMapArray(val, mapstep, i, mapType); } } if (mapstep == 0) { pix [i] = Color.grey; } else { // This doesn't actually calculate the slope per se, but it's faster // than asking for yet more elevation data. Please don't use this // code to operate nuclear power plants or rockets. double v1 = mapline [i]; if (i > 0) { v1 = Math.Max(v1, mapline [i - 1]); } if (i < mapline.Length - 1) { v1 = Math.Max(v1, mapline [i + 1]); } float v = Mathf.Clamp((float)Math.Abs(val - v1) / 1000f, 0, 2f); if (SCANcontroller.controller.colours == 1) { pix [i] = Color.Lerp(Color.black, Color.white, v / 2f); } else { if (v < 1) { pix [i] = Color.Lerp(XKCDColors.PukeGreen, XKCDColors.Lemon, v); } else { pix [i] = Color.Lerp(XKCDColors.Lemon, XKCDColors.OrangeRed, v - 1); } } } mapline [i] = val; } else if (mapmode == 2) { if (!data.isCovered(lon, lat, SCANdata.SCANtype.Biome)) { continue; } if (body.BiomeMap == null || body.BiomeMap.Map == null) { pix [i] = Color.Lerp(Color.black, Color.white, UnityEngine.Random.value); continue; } /* // this just basically stretches the actual biome map to fit... it looks horrible * float u = ((lon + 360 + 180 + 90)) % 360; * float v = ((lat + 180 + 90)) % 180; * if(u < 0 || v < 0 || u >= 360 || v >= 180) continue; * u /= 360f; v /= 180f; * pix[i] = body.BiomeMap.Map.GetPixelBilinear(u, v); */ double bio = data.getBiomeIndexFraction(lon, lat); Color biome = Color.grey; if (SCANcontroller.controller.colours == 1) { if ((i > 0 && mapline [i - 1] != bio) || (mapstep > 0 && mapline [i] != bio)) { biome = Color.white; } else { biome = Color.Lerp(Color.black, Color.white, (float)bio); } } else { Color elevation = Color.gray; if (data.isCovered(lon, lat, SCANdata.SCANtype.Altimetry)) { float val = 0f; if (mapType == 0) { val = big_heightmap[i, mapstep, SCANcontroller.controller.projection]; } if (val == 0) { if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes)) { val = (float)data.getElevation(lon, lat); heightMapArray(val, mapstep, i, mapType); } else { val = (float)data.getElevation(((int)(lon * 5)) / 5, ((int)(lat * 5)) / 5); heightMapArray(val, mapstep, i, mapType); } } elevation = Color.Lerp(Color.black, Color.white, Mathf.Clamp(val + 1500f, 0, 9000) / 9000f); } Color bio1 = XKCDColors.CamoGreen; Color bio2 = XKCDColors.Marigold; if ((i > 0 && mapline [i - 1] != bio) || (mapstep > 0 && mapline [i] != bio)) { //biome = Color.Lerp(XKCDColors.Puce, elevation, 0.5f); biome = Color.white; } else { biome = Color.Lerp(Color.Lerp(bio1, bio2, (float)bio), elevation, 0.5f); } } pix [i] = biome; mapline [i] = bio; } } map.SetPixels(0, mapstep, map.width, 1, pix); mapstep++; if (mapstep % 10 == 0 || mapstep >= map.height) { map.Apply(); } return(map); }
private static void drawMapLabels(Rect maprect, Vessel vessel, SCANmap map, SCANdata data) { foreach(Vessel v in FlightGlobals.Vessels) { if(v.mainBody == vessel.mainBody) { if(v.vesselType == VesselType.Flag && SCANcontroller.controller.map_flags) { drawVesselLabel(maprect, map, 0, v); } } } if(SCANcontroller.controller.map_markers) { foreach(SCANdata.SCANanomaly anomaly in data.getAnomalies()) { drawAnomalyLabel(maprect, map, anomaly); } } drawVesselLabel(maprect, map, 0, vessel); }
private static void drawAnomalyLabel(Rect maprect, SCANmap map, SCANdata.SCANanomaly anomaly) { if(!anomaly.known) return; double lon = (anomaly.longitude + 360 + 180) % 360; double lat = (anomaly.latitude + 180 + 90) % 180; if(map != null) { lat = (map.projectLatitude(anomaly.longitude, anomaly.latitude) + 90) % 180; lon = (map.projectLongitude(anomaly.longitude, anomaly.latitude) + 180) % 360; lat = map.scaleLatitude(lat); lon = map.scaleLongitude(lon); if(lat < 0 || lon < 0 || lat > 180 || lon > 360) return; } lon = lon * maprect.width / 360f; lat = maprect.height - lat * maprect.height / 180f; string txt = SCANcontroller.controller.anomalyMarker + " " + anomaly.name; if(!anomaly.detail) txt = SCANcontroller.controller.anomalyMarker + " Anomaly"; Rect r = new Rect(maprect.x + (float)lon, maprect.y + (float)lat, 250f, 25f); drawLabel(r, cb_yellow, txt, true, true); }
protected void doScanPass(SCANvessel vessel, double UT, double startUT, double lastUT, double llat, double llon) { Vessel v = vessel.vessel; SCANdata data = getData(v.mainBody); double soi_radius = v.mainBody.sphereOfInfluence - v.mainBody.Radius; double alt = v.altitude, lat = fixLatitude(v.latitude), lon = fixLongitude(v.longitude); double res = 0; Orbit o = v.orbit; bool uncovered; if (scanQueue == null) { scanQueue = new Queue <double>(); } if (scanQueue.Count != 0) { scanQueue.Clear(); } loop: // don't look at me like that, I just unrolled the recursion if (res > 0) { if (double.IsNaN(UT)) { goto dequeue; } if (o.ObT <= 0) { goto dequeue; } if (double.IsNaN(o.getObtAtUT(UT))) { goto dequeue; } Vector3d pos = o.getPositionAtUT(UT); double rotation = 0; if (v.mainBody.rotates) { rotation = (360 * ((UT - scan_UT) / v.mainBody.rotationPeriod)) % 360; } alt = v.mainBody.GetAltitude(pos); lat = fixLatitude(v.mainBody.GetLatitude(pos)); lon = fixLongitude(v.mainBody.GetLongitude(pos) - rotation); if (alt < 0) { alt = 0; } if (res > maxRes) { maxRes = (int)res; } } else { alt = v.heightFromTerrain; if (alt < 0) { alt = v.altitude; } } if (Math.Abs(lat - llat) < 1 && Math.Abs(lon - llon) < 1 && res > 0) { goto dequeue; } actualPasses++; uncovered = res <= 0; foreach (SCANsensor sensor in knownVessels[v.id].sensors.Values) { if (res <= 0) { if (data.getCoverage(sensor.sensor) > 0) { uncovered = false; } } sensor.inRange = false; sensor.bestRange = false; if (alt < sensor.min_alt) { continue; } if (alt > Math.Min(sensor.max_alt, soi_radius)) { continue; } sensor.inRange = true; double fov = sensor.fov; //double ba = Math.Min(sensor.best_alt, soi_radius); //if(alt < ba) fov = (alt / ba) * fov; //else sensor.bestRange = true; double surfscale = 600000d / v.mainBody.Radius; if (surfscale < 1) { surfscale = 1; } surfscale = Math.Sqrt(surfscale); fov *= surfscale; if (fov > 20) { fov = 20; } int f = (int)Math.Truncate(fov); int f1 = f + (int)Math.Round(fov - f); double clampLat; double clampLon; for (int x = -f; x <= f1; ++x) { clampLon = lon + x; // longitude does not need clamping /*if (clampLon < 0 ) clampLon = 0; */ /*if (clampLon > 360) clampLon = 360; */ for (int y = -f; y <= f1; ++y) { clampLat = lat + y; if (clampLat > 90) { clampLat = 90; } if (clampLat < -90) { clampLat = -90; } data.registerPass(clampLon, clampLat, sensor.sensor); } } } if (uncovered) { return; } /* * if(v.mainBody == FlightGlobals.currentMainBody) { * if(res > 0) data.map_small.SetPixel((int)Math.Round(lon) + 180, (int)Math.Round(lat) + 90, Color.magenta); * else data.map_small.SetPixel((int)Math.Round(lon) + 180, (int)Math.Round(lat) + 90, Color.yellow); * } */ if (vessel.lastUT <= 0) { return; } if (vessel.frame <= 0) { return; } if (v.LandedOrSplashed) { return; } if (res >= timeWarpResolution) { goto dequeue; } if (startUT > UT) { scanQueue.Enqueue((startUT + UT) / 2); scanQueue.Enqueue(startUT); scanQueue.Enqueue(UT); scanQueue.Enqueue(lat); scanQueue.Enqueue(lon); scanQueue.Enqueue(res + 1); } startUT = UT; UT = (lastUT + UT) / 2; llat = lat; llon = lon; res = res + 1; goto loop; dequeue: if (scanQueue.Count <= 0) { return; } UT = scanQueue.Dequeue(); startUT = scanQueue.Dequeue(); lastUT = scanQueue.Dequeue(); llat = scanQueue.Dequeue(); llon = scanQueue.Dequeue(); res = scanQueue.Dequeue(); goto loop; }
public void registerPass(CelestialBody body, float lon, float lat, SCANdata.SCANtype type) { getData(body).registerPass(lon, lat, type); }
//Reset the resource value array - quicker than rebuildKethaneData (), called on map resets private void rebuildResourceValue (SCANdata.SCANtype type) { if (!rebuildingValue) { print("[SCAN Kethane] Rebuilding Value Array"); rebuildingValue = true; } SCANdata data = SCANUtil.getData(body); for (int ilat = 4 * rebuildValueStep; ilat < 4 * (rebuildValueStep + 1); ilat++) { for (int ilon = 0; ilon < 360; ilon++) { if (SCANUtil.isCovered(ilon, ilat, body, (int)type)) { if (data.kethaneValueMap[ilon, ilat] == 0) { //Only check unassigned values cell = getKethaneCell(ilon - 180, ilat - 90); double? depositValue = KethaneData.Current[resource.name][body].Resources.GetQuantity(cell); if (depositValue != null) updateResourceValue (ilon, ilat, depositValue, data); else updateResourceValue (ilon, ilat, -1d, data); //Give empty cells -1 resources, account for this later on } } } } rebuildValueStep++; if (rebuildValueStep >= 45) { print("[SCAN Kethane] Value Array Rebuilt"); rebuildingValue = false; } }
private void updateResourceArray (int lon, int lat, SCANdata.SCANtype type, SCANdata data) { data.coverage[lon, lat] |= (Int32)type; }
private void updateResourceValue (int lon, int lat, double? value, SCANdata data) { data.kethaneValueMap[lon, lat] = (float)value; }
public void registerSensor(Guid id, SCANdata.SCANtype sensors, double fov, double min_alt, double max_alt, double best_alt) { if(!knownVessels.ContainsKey(id)) knownVessels[id] = new SCANvessel(); SCANvessel sv = knownVessels[id]; sv.id = id; foreach(SCANdata.SCANtype sensor in Enum.GetValues(typeof(SCANdata.SCANtype))) { if(countBits((int)sensor) != 1) continue; if((sensor & sensors) == SCANdata.SCANtype.Nothing) continue; double this_fov = fov, this_min_alt = min_alt, this_max_alt = max_alt, this_best_alt = best_alt; if(this_max_alt <= 0) { this_min_alt = 5000; this_max_alt = 500000; this_best_alt = 200000; this_fov = 5; if((sensor & SCANdata.SCANtype.AltimetryHiRes) != SCANdata.SCANtype.Nothing) this_fov = 3; if((sensor & SCANdata.SCANtype.AnomalyDetail) != SCANdata.SCANtype.Nothing) { this_min_alt = 0; this_max_alt = 2000; this_best_alt = 0; this_fov = 1; } } if(!sv.sensors.ContainsKey(sensor)) sv.sensors[sensor] = new SCANsensor(); SCANsensor s = sv.sensors[sensor]; s.sensor = sensor; s.fov = this_fov; s.min_alt = this_min_alt; s.max_alt = this_max_alt; s.best_alt = this_best_alt; } }
public ScienceData getAvailableScience(Vessel v, SCANdata.SCANtype sensor, bool notZero) { SCANdata data = getData(v.mainBody); ScienceData sd = null; ScienceExperiment se = null; ScienceSubject su = null; bool found = false; string id = null; double coverage = 0f; if (v.mainBody.pqsController != null) { if (!found && (sensor & SCANdata.SCANtype.AltimetryLoRes) != SCANdata.SCANtype.Nothing) { found = true; id = "SCANsatAltimetryLoRes"; coverage = data.getCoveragePercentage(SCANdata.SCANtype.AltimetryLoRes); } if (!found && (sensor & SCANdata.SCANtype.AltimetryHiRes) != SCANdata.SCANtype.Nothing) { found = true; id = "SCANsatAltimetryHiRes"; coverage = data.getCoveragePercentage(SCANdata.SCANtype.AltimetryHiRes); } } if (v.mainBody.BiomeMap != null) { if (!found && (sensor & SCANdata.SCANtype.Biome) != SCANdata.SCANtype.Nothing) { found = true; id = "SCANsatBiomeAnomaly"; coverage = data.getCoveragePercentage(SCANdata.SCANtype.Biome | SCANdata.SCANtype.Anomaly); } } if (!found) { return(null); } se = ResearchAndDevelopment.GetExperiment(id); if (se == null) { return(null); } su = ResearchAndDevelopment.GetExperimentSubject(se, ExperimentSituations.InSpaceHigh, v.mainBody, "surface"); if (su == null) { return(null); } print("[SCANsat] coverage " + coverage.ToString("F1") + ", science cap " + su.scienceCap.ToString("F1") + ", subject value " + su.subjectValue.ToString("F2") + ", science value " + su.scientificValue.ToString("F2") + ", science " + su.science.ToString("F2")); su.scientificValue = 1; float science = (float)coverage; if (science > 95) { science = 100; } if (science < 30) { science = 0; } science = science / 100f; science = Mathf.Max(0, (science * su.scienceCap) - su.science); print("[SCANsat] remaining science: " + science.ToString("F1") + ", base = " + (se.baseValue).ToString("F1")); science /= Mathf.Max(0.1f, su.scientificValue); science /= su.subjectValue; print("[SCANsat] result = " + science.ToString("F2")); if (notZero && science <= 0) { science = 0.00001f; } sd = new ScienceData(science, 1f, 0f, id, se.experimentTitle + " of " + v.mainBody.theName); sd.subjectID = su.id; return(sd); }
public SCANsensor getSensorStatus(Vessel v, SCANdata.SCANtype sensor) { if(!knownVessels.ContainsKey(v.id)) return null; if(!knownVessels[v.id].sensors.ContainsKey(sensor)) return null; return knownVessels[v.id].sensors[sensor]; }
public bool isVesselKnown(Guid id, SCANdata.SCANtype sensor) { if(!knownVessels.ContainsKey(id)) return false; SCANdata.SCANtype all = SCANdata.SCANtype.Nothing; foreach(SCANdata.SCANtype s in knownVessels[id].sensors.Keys) all |= s; return (all & sensor) != SCANdata.SCANtype.Nothing; }
//Update the Kethane database - used after background scanning private void updateKethaneData (SCANdata.SCANtype type) { print("[SCAN Kethane] Updating Kethane Database"); for (int ilat = 0; ilat < 180; ilat++) { for (int ilon = 0; ilon < 360; ilon++) { if (SCANUtil.isCovered (ilon, ilat, body, (int)type)) { cell = getKethaneCell (ilon - 180, ilat - 90); if (!KethaneData.Current[resource.name][body].IsCellScanned(cell)) { KethaneData.Current[resource.name][body].ScanCell(cell); } } } } }
public void registerSensor(Vessel v, SCANdata.SCANtype sensors, double fov, double min_alt, double max_alt, double best_alt) { registerSensor(v.id, sensors, fov, min_alt, max_alt, best_alt); knownVessels[v.id].vessel = v; knownVessels[v.id].latitude = fixLatitude(v.latitude); knownVessels[v.id].longitude = fixLongitude(v.longitude); }
private ScienceData getAvailableScience(SCANtype sensor, bool notZero) { SCANdata data = SCANUtil.getData(vessel.mainBody); if (data == null) { return(null); } ScienceData sd = null; ScienceExperiment se = null; ScienceSubject su = null; bool found = false; string id = null; double coverage = 0f; float multiplier = 1f; if (!found && (sensor & SCANtype.AltimetryLoRes) != SCANtype.Nothing) { found = true; if (vessel.mainBody.pqsController == null) { multiplier = 0.5f; } id = "SCANsatAltimetryLoRes"; coverage = SCANUtil.getCoveragePercentage(data, SCANtype.AltimetryLoRes); } else if (!found && (sensor & SCANtype.AltimetryHiRes) != SCANtype.Nothing) { found = true; if (vessel.mainBody.pqsController == null) { multiplier = 0.5f; } id = "SCANsatAltimetryHiRes"; coverage = SCANUtil.getCoveragePercentage(data, SCANtype.AltimetryHiRes); } else if (!found && (sensor & SCANtype.Biome) != SCANtype.Nothing) { found = true; if (vessel.mainBody.BiomeMap == null) { multiplier = 0.5f; } id = "SCANsatBiomeAnomaly"; coverage = SCANUtil.getCoveragePercentage(data, SCANtype.Biome); } if (!found) { return(null); } se = ResearchAndDevelopment.GetExperiment(id); if (se == null) { return(null); } su = ResearchAndDevelopment.GetExperimentSubject(se, ExperimentSituations.InSpaceHigh, vessel.mainBody, "surface"); if (su == null) { return(null); } su.scienceCap *= multiplier; SCANUtil.SCANlog("Coverage: {0}, Science cap: {1}, Subject value: {2}, Scientific value: {3}, Science: {4}", new object[5] { coverage.ToString("F1"), su.scienceCap.ToString("F1"), su.subjectValue.ToString("F2"), su.scientificValue.ToString("F2"), su.science.ToString("F2") }); su.scientificValue = 1; float science = (float)coverage; if (science > 95) { science = 100; } if (science < 30) { science = 0; } science = science / 100f; science = Mathf.Max(0, (science * su.scienceCap) - su.science); SCANUtil.SCANlog("Remaining science: {0}, Base value: {1}", new object[2] { science.ToString("F1"), se.baseValue.ToString("F1") }); science /= Mathf.Max(0.1f, su.scientificValue); //look 10 lines up; this is always 1... science /= su.subjectValue; SCANUtil.SCANlog("Resulting science value: {0}", new object[1] { science.ToString("F2") }); if (notZero && science <= 0) { science = 0.00001f; } sd = new ScienceData(science * su.dataScale, 1f, 0f, su.id, se.experimentTitle + " of " + vessel.mainBody.theName); su.title = sd.title; return(sd); }
public void unregisterSensor(Vessel v, SCANdata.SCANtype sensors) { if(!knownVessels.ContainsKey(v.id)) return; SCANvessel sv = knownVessels[v.id]; sv.id = v.id; sv.vessel = v; foreach(SCANdata.SCANtype sensor in Enum.GetValues(typeof(SCANdata.SCANtype))) { if((sensors & sensor) == SCANdata.SCANtype.Nothing) continue; if(!sv.sensors.ContainsKey(sensor)) continue; sv.sensors.Remove(sensor); } }
public override void OnLoad(ConfigNode node) { body_data.Clear(); ConfigNode node_vessels = node.GetNode("Scanners"); if (node_vessels != null) { print("SCANsat Controller: Loading " + node_vessels.CountNodes.ToString() + " known vessels"); foreach (ConfigNode node_vessel in node_vessels.GetNodes("Vessel")) { Guid id = new Guid(node_vessel.GetValue("guid")); string stext = node_vessel.GetValue("sensors"); if (stext != null && stext != "") { int sensors = Convert.ToInt32(stext); if (sensors != 0) { registerSensor(id, (SCANdata.SCANtype)sensors, 0, 0, 0, 0); } } foreach (ConfigNode node_sensor in node_vessel.GetNodes("Sensor")) { int sensor = Convert.ToInt32(node_sensor.GetValue("type")); double fov = Convert.ToDouble(node_sensor.GetValue("fov")); double min_alt = Convert.ToDouble(node_sensor.GetValue("min_alt")); double max_alt = Convert.ToDouble(node_sensor.GetValue("max_alt")); double best_alt = Convert.ToDouble(node_sensor.GetValue("best_alt")); registerSensor(id, (SCANdata.SCANtype)sensor, fov, min_alt, max_alt, best_alt); } } } ConfigNode node_progress = node.GetNode("Progress"); if (node_progress != null) { foreach (ConfigNode node_body in node_progress.GetNodes("Body")) { string body_name = node_body.GetValue("Name"); print("SCANsat Controller: Loading map for " + body_name); CelestialBody body = FlightGlobals.Bodies.FirstOrDefault(b => b.name == body_name); if (body != null) { SCANdata data = SCANUtil.getData(body); try { string mapdata = node_body.GetValue("Map"); data.deserialize(mapdata); } catch (Exception e) { print(e.ToString()); print(e.StackTrace); // fail somewhat gracefully; don't make the save unloadable } data.disabled = Convert.ToBoolean(node_body.GetValue("Disabled")); } } } if (!warned && SCANversions.SCANurl != "SCANsat/Plugins" && !string.IsNullOrEmpty(SCANversions.SCANurl)) { //Complain if SCANsat is installed in the wrong place ScreenMessages.PostScreenMessage(string.Format("SCANsat plugin installed in the wrong directory: {0}. Installation location should be:/nKerbal Space Program/GameData/SCANsat/Plugins/SCANsat.dll", SCANversions.SCANurl), 15f, ScreenMessageStyle.UPPER_CENTER); warned = true; } }