Jump to content

alexalex

Members
  • Posts

    28
  • Joined

  • Last visited

Reputation

20 Excellent

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. There isn't actually any satellite mod that does this, though I'm working on creating a science only version of Kerbalism that does this among having various other improvements (I've got this part all worked out and fully functional though it was an absolute PITA to code). It's why I asked whether something like this would be in KSP 2, since when I read about the science update I immediately thought of what I'd recently finished coding and how something similar would be a vast improvement over KSP 1 that KSP 2 could include.
  2. So I have a couple questions... How will the experiments work? Will they be over time experiments that can take anything from minutes to years (hopefully)? And if so how does that interact with the satellite data transmission system? For example if I have a relay network set up around a planet and start sending data from a vessel on the surface will it consume bandwidth across the network, and so reduce how much is available for other vessels linked to that network? There's the possibility for a lot of interesting dynamics and interactions there.
  3. Update : Nothing I tried was able to solve the issue directly since it just seems to be hard baked into the KSP code. The only way I found around it was to either override the UpdateDisplay() method of CommNetUI, or joyride on top of it at runtime which is what I ended up doing, since that allowed me to code out a mod conflict. On the plus side I think I'm getting close to being able to release something. For posterity here is the code I ended up using. Now compare this to the *short* class I initially wrote above... [HarmonyPatch] public static class CommNetPatch { private static CommViewer commViewer; // prefix patch method [HarmonyPrefix] public static void PreFix() { if (commViewer == null) { commViewer = new CommViewer(); } commViewer.LineDisplay(); } // target method that determines which method to patch [HarmonyTargetMethod] public static MethodBase TargetingMethod() { // conditional that checks if the CommNetConstellation mod is present bool hasCNC = false; foreach (var a in AssemblyLoader.loadedAssemblies) { if (a.name == "CommNetConstellation") // check for CNC { hasCNC = true; break; } } // returns the appropriate method to patch depending on if CommNetConstellation is present if (hasCNC) { return AccessTools.Method(Type.GetType("CommNetConstellation.CommNetLayer.CNCCommNetUI, CommNetConstellation"), "UpdateDisplay"); } else { return AccessTools.Method(typeof(CommNetUI), "UpdateDisplay"); } } } public class CommViewer : MonoBehaviour { public void LineDisplay() { // destroy the old gameobject to delete existing lines so their positions can be refreshed GameObject oldLineObject = GameObject.Find("CommViewerLine"); if (oldLineObject != null) { Destroy(oldLineObject); } if (Monitor.commStatus != "<b> << Available Bandwidth >> </b>") { return; } // create a list of commlinks removing any duplicates HashSet<CommLink> uniqueLinks = new HashSet<CommLink>(new PrecisePositionComparer()); foreach (Vessel v in FlightGlobals.Vessels) { if (v.connection != null) { foreach (CommLink link in v.connection.ControlPath) { if (!uniqueLinks.Contains(link)) { uniqueLinks.Add(link); } } } } // iterate over the commlink list and store the vessel coordinates as well as startVessel in a new list via a tuple List<Tuple<Vector3, Vector3, Vessel>> linePositions = new List<Tuple<Vector3, Vector3, Vessel>>(); foreach (CommLink link in uniqueLinks) { Vessel startVessel = CommHandlerCommNetBase.CommNodeToVessel(link.start); Vector3d start = ScaledSpace.LocalToScaledSpace(startVessel.GetWorldPos3D()); Vessel endVessel = CommHandlerCommNetBase.CommNodeToVessel(link.end); Vector3d end; if (!link.end.isHome) { end = ScaledSpace.LocalToScaledSpace(endVessel.GetWorldPos3D()); } else end = ScaledSpace.LocalToScaledSpace(link.end.precisePosition); // this only updates once per second so where possible use GetWorldPos3D() instead // create a new tuple containing the start and end vector3 coordinates and startVessel Tuple<Vector3, Vector3, Vessel> lineSegment = new Tuple<Vector3, Vector3, Vessel>(start, end, startVessel); // add the tuple to the list linePositions.Add(lineSegment); } // create a parent GameObject for the lines GameObject lineObject = new GameObject("CommViewerLine"); UnityEngine.LineRenderer line = lineObject.AddComponent<UnityEngine.LineRenderer>(); // use a foreach loop to iterate over the list and create a child LineRenderer for each pair of coordinates foreach (Tuple<Vector3, Vector3, Vessel> tuple in linePositions) { GameObject childLineObject = new GameObject("ChildLine"); childLineObject.transform.parent = lineObject.transform; UnityEngine.LineRenderer childLine = childLineObject.AddComponent<UnityEngine.LineRenderer>(); // set the start and end positions of the line using tuple.Item1 and tuple.Item2 childLine.positionCount = 2; childLine.SetPositions(new Vector3[] { tuple.Item1, tuple.Item2 }); Camera cam = PlanetariumCamera.Camera; Vector3d cam3d = cam.transform.position; float start = (float)Vector3d.Distance(cam3d, childLine.GetPosition(0)); float end = (float)Vector3d.Distance(cam3d, childLine.GetPosition(1)); // set the line width so it scales properly with zoom level childLine.startWidth = start * 5 / 1000; childLine.endWidth = end * 5 / 1000; childLine.material = CommNetUI.TelemetryMaterial; childLine.material.SetTexture("lineTex", CommNetUI.TelemetryTexture); // Use tuple.Item3 to access the startVessel so we can make the line color vary with signal strength Vessel startVessel = tuple.Item3; float signalStrength = (float)startVessel.KerbalismData().Connection.strength; (Color startColor, Color endColor) = MixColors(signalStrength); // now make the line nice and pretty SetColorGradient(childLine, startColor, endColor); if (MapView.Draw3DLines) { childLine.gameObject.layer = 31; childLine.useWorldSpace = true; } else { childLine.gameObject.layer = 10; childLine.useWorldSpace = false; } } } public (Color, Color) MixColors(float percentage) { // define the two pairs of colors to mix Color color1a = Color.Lerp(new Color(0f, 1f, 0f, 1f), Color.clear, 0.3f); Color color1b = Color.Lerp(new Color(1f, 0f, 0f, 1f), Color.clear, 0.3f); Color color2a = Color.Lerp(new Color(0.004f, 0.196f, 0.125f), Color.clear, 0.3f); Color color2b = Color.Lerp(new Color(0.310f, 0f, 0f, 1f), Color.clear, 0.3f); // calculate the percentage for the other color float otherPercentage = 1f - percentage; // mix the first pair of colors using the percentage and its complement Color mixedColor1 = color1a * percentage + color1b * otherPercentage; // mix the second pair of colors using the same percentage and its complement Color mixedColor2 = color2a * percentage + color2b * otherPercentage; // return the two mixed colors return (mixedColor1, mixedColor2); } public static void SetColorGradient(UnityEngine.LineRenderer childLine, Color startColor, Color endColor, float startAlpha = 1, float endAlpha = 1) { Gradient gradient = new Gradient(); gradient.SetKeys( new GradientColorKey[] { new GradientColorKey(startColor, 0.0f), new GradientColorKey(endColor, 1.0f) }, new GradientAlphaKey[] { new GradientAlphaKey(startAlpha, 0.0f), new GradientAlphaKey(endAlpha, 1.0f) } ); childLine.colorGradient = gradient; } } class PrecisePositionComparer : IEqualityComparer<CommLink> { public bool Equals(CommLink x, CommLink y) { // Check if x and y are null if (x == null && y == null) return true; if (x == null || y == null) return false; // compare the start and end precise positions of x and y return x.a.precisePosition == y.a.precisePosition && x.b.precisePosition == y.b.precisePosition; } public int GetHashCode(CommLink obj) { // return a hash code based on the precise positions of obj return obj.a.precisePosition.GetHashCode() ^ obj.b.precisePosition.GetHashCode(); } }
  4. Can't see the log because its too big for github to show. But have you tried used debug.log to log to the console to determine the line of code that's causing the error?
  5. Update : Looking further at it appears that whenever the camera position moves the line lags behind where it should be, and the jitter is it jumping ahead and trying to catch up to where it should be, instead of it being fixed to the vessel coordinates and moving smoothly with them. Then when I stop moving the camera it catches up which is why there is no jitter then. But I still don't know what is causing it.
  6. I am trying to make the satellite and relay system operate a bit like how data connections work in real life so that experiments consume antenna bandwidth while antennas provide network capacity. So that each additional experiment that is being run would consume bandwidth and reduce the available capacity of the satellite relay network that it is on (I have this part mostly done). But to make it work I need an easy to understand way to show the KSP player what is going on, and I'm running into trouble with the graphical interface part. I can draw lines between the start and end points of a particular satellite relay network, but whenever I rotate the camera position the lines jitter and wobble about and I have no idea what's causing it. Vanilla KSP doesn't do this so it's definitely something to do with my code. Anyone know what's going on? public class CommViewer : CommNetUI { public void Update() { if (line != null) VectorLine.Destroy(ref line); if (Monitor.commStatus != "<b> << Available Bandwidth >> </b>") return; var vesselList = new List<Vessel>(); foreach (Vessel v in FlightGlobals.Vessels) { if (v.connection != null && !v.connection.ControlPath.First.end.isHome) { Vessel endVessel = CommHandlerCommNetBase.CommNodeToVessel(v.Connection.ControlPath.First.end); vesselList.Add(endVessel); } } CommPath path = null; foreach (Vessel v in FlightGlobals.Vessels) { if (v.connection != null && !vesselList.Contains(v)) { path = v.connection.ControlPath; } } List<Vector3> points = new List<Vector3>(); path.GetPoints(points, true); ScaledSpace.LocalToScaledSpace(points); CreateLine(ref line, points); line.SetColor(Color.Lerp(new Color(0f, 1f, 1f), Color.clear, 0.3f)); if (MapView.Draw3DLines) { line.SetWidth(lineWidth3D); line.Draw3D(); } else { line.SetWidth(lineWidth2D = 1f); line.Draw(); } } }
  7. FYI even if they were still only bug fixing, the frequency of updates would still slow down. Dev's fix the big high impact easy to fix bugs first. The big high impact hard to fix bugs usually aren't bugs at all but rather relate to issues involving deep fundamental code design and require a lot more work since a hefty chunk of code has to be rewritten. That results in slower updates.
  8. You can do this through a module manager cfg file since stock ksp already has an upgrades feature built into it and module manager can take advantage of that. It's the simplest and easiest way without the need to do any c# hard coding. There's two parts to it. First you need to specify the tech node at which the upgrade unlocks at via PARTUPGRADE and secondly add the upgrade itself to the part config file via UPGRADES. https://github.com/rspeed/Porkjet-Parts-Overhaul/releases The above mod while old adds upgrades to existing parts so you should be able to follow those examples. The link below also contrains lots of useful info and links to more mods containing part upgrades.
  9. Lol. As someone fairly new to coding myself and who's been teaching myself the ins and outs of how to code for KSP1 (I've still got a long way to go), you'll want microsoft visual studio which is free and to download some existing simple mods to see how they work internally. C# as a language makes sense but like any language you'll need to know its grammar, syntax, and structure to use it properly. I'd also suggest using bing chatgpt as it can answer questions much faster than the hours it might take you to trawl through stackoverflow for an answer (this forum is pretty dead for getting answers on coding questions), but bear in mind its not always right. Good luck!
  10. I have not done it myself but maybe via FlightGlobals.ActiveVessel.transform?
  11. There's definitely been a boost to recent player count numbers. https://steamcharts.com/app/220200#1y
  12. Have you ever coded anything? Its pretty clear this game is in the early stages (probably shouldn't be released just yet) with missing core fundamentals such as heat transfer etc, and as such it looks to be very unoptimized. Personally, I think they are releasing it now because those are the orders from on high they have received rather than thinking its ready themselves which explains the current state of things. It also doesn't take very much at all for a game, any game, to slow a comp to a crawl. Just one bad piece of code will do it, and clearly given the letter from Nate he seems to know that there are some big bad pieces of code in there. So personally I don't think its the end of the world for KSP2 just yet, rather that its unfortunately following the trend of a lot of modern games and releasing before they should be due to shareholder and corporate pressures. Myself I will eagerly await EVE volumetrics, finish the mod update I'm working on, and play original KSP while KSP2 matures. Eventually KSP2 will surpass KSP1 but it won't be in the first few months after EA release.
  13. After bashing my head against the wall some more I found the fix for this - scrapping the part list method of hooking into KSPEvents entirely. It drastically simplified the code too.
  14. Going EVA scrambles the ordering of fields and events due to the ShowUpgradeStats event button disappearing on EVA, and how that interacts with KSP's own internal part field/event ordering system. To solve this I've made the ShowUpgradeStats button permanent, but the problem is that this then causes buttons on different parts to mix and duplicate while other buttons that should unload don't. I did find this old post where someone else was having the same/similar issue as me but their solution didn't work when I tried to apply it to my code. So does anyone know how I can fix this duplication issue or another way I can make the original field/event order permanent? Here's the code I've been using for ShowUpgradeStats. public void Start() { List<Part> parts = FlightGlobals.ActiveVessel.parts; for (int i = 0; i < parts.Count; i++) { Part p = parts.ElementAt(i); foreach (BaseEvent ShowUpgradeStats in p.Events) { int id = ShowUpgradeStats.id; p.Events[id].guiActiveUnfocused = true; } } }
  15. Update : I figured it out though its probably not the most elegant method. I'm putting it out here anyway though in case its useful to someone else at some point. I used boolean true or false and get/set accessors so that a part window update gets triggered whenever false changes to true or vice versa. Like so - private bool _UpdateGUI; public bool UpdateGUI { get { return _UpdateGUI; } set { if (value != _UpdateGUI) { part.PartActionWindow.displayDirty = true; } _UpdateGUI = value; } } // And public virtual void FixedUpdate() { if (Lib.IsEditor() && sample_amount > 0) { Capacity = sample_amount.ToString("F2") + " " + Local.SCIENCEARCHIVE_samples; Fields["Capacity"].guiActiveEditor = true; } if (Lib.IsFlight() && (remainingSampleMass / ExpInfo.SampleMass) > 0) { Capacity = (remainingSampleMass / ExpInfo.SampleMass).ToString("F2") + " " + Local.SCIENCEARCHIVE_samples; Fields["Capacity"].guiActive = true; UpdateGUI = false; } else if (Lib.IsFlight() && (remainingSampleMass / ExpInfo.SampleMass) <= 0) { Fields["Capacity"].guiActive = false; UpdateGUI = true; }
×
×
  • Create New...