• Content Count

  • Joined

  • Last visited

Community Reputation

1,080 Excellent


About xEvilReeperx

  • Rank
    Junior Rocket Scientist

Recent Profile Visitors

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

  1. AudioClip clip = GameDatabase.Instance.GetAudioClip(gdb_path); clip.name = name; // <----- bad plan planetMap.Add(name, clip); fileNames.Add(clip, name); I haven't tried running your code but at a glance this stands out. Usually the GameDatabase names are the GameData-relative URLs, so on your first run this clip will likely be named something like SoundsOfSpace/Sounds/SoundsOfSpace/yourfile After successfully finding this clip the first time, you inexplicably rename it to yourfile.ogg. This will be a problem because GameDatabase.Instance.ExistsAudioClip is checking the clip names for a match
  2. This is precisely why I won't incorporate the work of others into my own stuff: a large number of these licenses have either been poisoned by unwritten rules or do not reflect the actual intent of the owner who has copy-pasted it from somewhere, and so they might as well be All Rights Reserved. Secret, unwritten rules are not transparency. If I look at a license that says YOU MAY DO ANYTHING WITH THIS WORK and think, gee, I'll have to make sure that's true, then the license is incomplete at best and useless at worst.
  3. xEvilReeperx

    About to pull out my hair

    You've nearly got it. Your issue is that your window rect is in screen space (0,0 = top left) while ReadPixels (and CopyTexture) expects pixel space (0,0 = bottom left) Convert to pixel space by inverting the y coordinate (Screen.height - y) and subtracting out the window height to get the bottom-left corner of the window [KSPAddon(KSPAddon.Startup.MainMenu, false)] class CaptureWindowScreenshot : MonoBehaviour { private Rect _windowRect = new Rect(Screen.width * 0.5f, Screen.height * 0.5f - 200, 200f, 50f); private readonly GUILayoutOption[] _defaultOptions = new GUILayoutOption[0]; private GUI.WindowFunction _windowFunc; private bool _capture = false; private void Awake() { _windowFunc = DrawWindow; } private void OnGUI() { _windowRect = KSPUtil.ClampRectToScreen(GUILayout.Window(GetInstanceID(), _windowRect, _windowFunc, "Test Window", _defaultOptions)); if (_capture && Event.current.type == EventType.Repaint) { _capture = false; StartCoroutine(Capture()); } } private IEnumerator Capture() { yield return new WaitForEndOfFrame(); var pixelRect = _windowRect; // copy values pixelRect.y = Mathf.Max(Screen.height - _windowRect.y - _windowRect.height, 0f); var captureTex = new Texture2D(Mathf.CeilToInt(pixelRect.width), Mathf.CeilToInt(pixelRect.height)); captureTex.ReadPixels(pixelRect, 0, 0, false); captureTex.SaveToDisk("window.png"); // your preferred method here Destroy(captureTex); } private void DrawWindow(int winid) { for (int i = 0; i < 5; ++i) GUILayout.Label("Text goes here", _defaultOptions); GUILayout.Space(5f); if (GUILayout.Button("Capture this window", _defaultOptions)) _capture = true; GUI.DragWindow(); } }
  4. xEvilReeperx

    PAW Event being disabled

    From easiest to most convoluted: Cheat by implementing a similarly-named KSPEvent (with different method name) and abusing GameObject.SendMessage Reimplement the method yourself (VesselRenameDialog looks interesting) Fix the cached reflected delegate data yourself. This will make things "just work", but it's a little hacky [KSPAddon(KSPAddon.Startup.MainMenu, true)] class FixSetVesselNamingIssue : MonoBehaviour { class SneakyWayIntoCachedReflectedData : BaseEventList { public SneakyWayIntoCachedReflectedData(Type nobodyCares) : base(nobodyCares) { EnsureDataExists<Part>(); // if ALL modules changed, might not be any cached data for Part EnsureDataExists<PartTapIn>(); // it's possible some MM failure didn't edit the parts as expected, so confirm here too // "reflectedAttributeCache" is part of BaseEventList and is why we derive from it -> to get access so // we can tweak it var partData = reflectedAttributeCache[typeof(Part)]; // <-- this has an event we want to copy var tapinData = reflectedAttributeCache[typeof(PartTapIn)]; // <-- this is where we'll copy it to // unfortunately the only way to tell the various attributes apart // is to examine their guiName, which is localized #autoLOC_8003140 var targetLocalizedName = Localizer.Format("#autoLOC_8003140"); var configureNamingAttr = partData.eventAttributes.Single(kspe => kspe.guiName.Equals(targetLocalizedName, StringComparison.Ordinal)); if (tapinData.eventAttributes.Any( kspe => kspe.guiName.Equals(targetLocalizedName, StringComparison.Ordinal))) { return; // clearly changes already made } // insert attribute into PartTapIn data tapinData.eventAttributes.Add(configureNamingAttr); // copy "SetVesselNaming" delegate from Part to PartTapIn // this'll work because it's technically part of PartTapIn as well // note: method name directly, no localization needed here var setVesselNamingFunc = partData.eventDelegates.Single(mi => "SetVesselNaming".Equals(mi.Name)); tapinData.eventDelegates.Add(setVesselNamingFunc); } private static void EnsureDataExists<T>() where T : MonoBehaviour { if (reflectedAttributeCache.ContainsKey(typeof(T))) return; // already cached // if we create an inactive GameObject, we can prevent stuff from triggering // (awake, start) var dummyGo = new GameObject("dummy"); dummyGo.SetActive(false); // suppress awake, start var target = dummyGo.AddComponent<T>(); var dummy = new BaseEventList(target); // force data to be cached UnityEngine.Object.Destroy(dummyGo.gameObject); } } private void Start() { try { new SneakyWayIntoCachedReflectedData( typeof(Part)); // we literally don't care about anything but getting this constructor to run } catch (Exception e) { Debug.LogError("Exception while trying to meddle with cached data: " + e); } finally { Destroy(gameObject); // done } } }
  5. The exception in the log was the first clue. I looked at the code and didn't see any reason why that would prevent a simple print statement made in Update from working, so I wrote another small addon that checked out KeyNode's state. There were three possibilities as to why Update wasn't running: the component had been destroyed due to the uncaught exception in Awake. I've never seen this before, but thought it could be something AddonLoader does on an unhandled exception the GameObject wasn't active the MonoBehaviour was disabled (by Unity?) Turns out #3 was your problem
  6. It throws an uncaught exception in Awake and its MonoBehaviour ends up getting disabled (MonoBehaviour.enabled = false) when initializing for the second+ time. That's why you don't see any output from Update on subsequent flight scenes ArgumentException: An element with the same key already exists in the dictionary. System.Collections.Generic.Dictionary`2[UnityEngine.KeyCode,Callback].Add (KeyCode key, .Callback value) KeyNode.KeyNode.Awake () UnityEngine.GameObject:AddComponent(Type) AddonLoader:StartAddon(LoadedAssembly, Type, KSPAddon, Startup) AddonLoader:StartAddons(Startup) AddonLoader:OnLevelLoaded(GameScenes) AddonLoader:OnSceneLoaded(Scene, LoadSceneMode) UnityEngine.SceneManagement.SceneManager:Internal_SceneLoaded(Scene, LoadSceneMode)
  7. What does the hierarchy of your part look like? Based on the stacktrace and name, I'd bet there's a bug in StrippedTaggedTransforms. Try making sure whatever element is tagged with Icon_Only is the very last child of its parent, wherever the tag appears
  8. xEvilReeperx

    KSP 1.4.1 Performance

    Follow the same instructions to get debugging working, and then use Unity's profiler with KSP
  9. xEvilReeperx

    KSP 1.4.1 Performance

    You're going to have a hard time writing code that doesn't generate unnecessary garbage if you don't understand the mechanisms that create it. Use the profiler to find problem spots. If you happen to use VS and have Resharper, the Heap Allocations Viewer extension is very useful
  10. xEvilReeperx

    KSP 1.4.1 Performance

    Don't do this, it has every drawback and no advantage. They will all be rendered anyways and any change to any element will still dirty its canvas and trigger a rebuild
  11. You've misunderstood my point: KSP's source code is not required to do any of these things, so I don't have any obligation to offer it.
  12. I don't have any source code to KSP or Assembly-CSharp. I'm able to generate, install, run, and modify mods. Am I a magician?
  13. xEvilReeperx

    Does KSP v1.4 really have spyware in it?

    RedShell is apparently sending information whenever the game is launched (and whether game is modded). While the CALL_HOME, SEND_PROGRESS_DATA, and DONT_SEND_IP settings still exist, they are no longer used and there's no way to opt out of this data collection. Sent data includes your IP address and some kind of user ID which I assume is unique. I couldn't find anything related to Ghostery
  14. xEvilReeperx

    Simple way to know if debug menu is open?

    If you're polling instead of an infrequent check, it might be best to add a little tracking component to DebugScreen that updates a visible flag whenever OnEnable or OnDisable get called on it. The FindObject(s) family are all fairly slow
  15. xEvilReeperx

    Clarifying Legal Boundaries

    Last time a similar question was asked, the answer was no because making any changes to the game files outside of GameData is a no-no, and a double no because you would need to distribute the patched assembly afterwards. Patch the method itself at runtime instead without making modifications to the file on disk. Of course, I'm not 100% sure that's technically allowed either...