FtD Modding

Adventures in Modding

Due to some other games, I recently (like within the past 2-3 weeks) became interested in Unity Engine modding via injection. First by using IPA and then finally by using BepInEx. At first, I made a (heroic, I thought) attempt trying to add rudimentary VR support (by way of VRGIN) to From the Depths, but alas my C#/.NET/Unity/VR skills are still too low. FtD's Unity version is far too advanced of what VRGIN supports, even after trying various other forks/continuations.

A few days ago, I started from zero again: with just BepInEx installed. And then I set forth to make my first mod — the lifelong (ha ha) dream of being able to exfiltrate data generated by Lua scripts. I've needed such a feature for a long time now, especially for my more experimental scripts (such as the neural-net driven rocket aiming script). It sucked needing to relearn/retrain the script every time the vehicle was loaded/put into play. So it would be very useful to extract the training set (or even the final weights) and then hardcode them into a "production" version of the script.

Turned out much easier than I thought, since I simply patched 3 existing Lua methods:

  • Log — To save data (as a string)
  • ClearLogs — To clear anything saved
  • Crash — To dump all saved strings to a file (in the place where the game usually saves Lua scripts) and then clear the saved strings

Very easy to do. Simply made use of Harmony.

Then, I thought, I would really like that Lua method to fetch the current wave height under a given point. I could just patch an existing method (like GetTerrainAltitudeForPosition), but then I'd have to take care when I used those methods in my scripts. So instead, I would try to inject a new method.

Yes, I know Gladyon (the prolific-modder-turned-dev) had a framework for injecting Lua methods. But I felt like I really needed to learn how to do it on my own. And so yesterday, off I went, delving heavily into Mono.Cecil, Harmony, SLua.

  1. I stubbed my new method (called HelloThere) into LuaBinding via Mono.Cecil.
  2. Also stubbed the SLua "generated" method into Lua_LuaBinding, complete with attributes.
  3. Because I'm not a masochist that likes to deal with IL, I patched the actual implementations in using Harmony.
  4. And then, after some head-scratching, I realized I needed to also insert the new method into LuaBinding's metatable on the Lua side.

And it worked. Calling I:HelloThere() from a Lua box would generate the proper response in the console (I simply made it use Console.WriteLine for simplicity...) I was successful.

But then I realized, all I really need to do is step #4. So that will be my next attempt, after devising a simple framework to inject Lua methods...