• Add Review
  • Subscribe
  • Nominate
  • Submit Media
  • RSS

Logging system

This has been a busy month in ordinary life, so I haven't made as much progress in Forgotten Gates as I would've liked. The counter-action system is about halfway done, I would say. I've established the data class for holding counters in code, the spreadsheet page for generating their data, and the function for pulling the data into the plugin. Now I need to actually work it into the combat system.

I've also made my debug logging system a bit more sophisticated (C++ talk ahead, those not into that can skip the rest). Originally I just had a file pointer open and a couple of general patterns for pushing stuff into the file. Then I got the idea of having indents according to how many levels deep into functions the code was, so I updated all the function start and function end logging to do that. But it turned out I made a mistake and the indent didn't shrink as much as it should when a function ended, which meant I had a bunch of stuff to re-edit. e.ea All it really would've taken was a find/replace on a couple of files, but at that point I decided I should "work smarter, not harder" about this.

So I did some research on C++ logging libraries. You'd think there'd be plenty of those, and there are, but the ones I encountered didn't help much in my case. The first that caught my interest was Log for C++ (log4c++ for short), which is modeled after Log4j, an industry-standard Java logging library. Unfortunately log4cpp can't just be dropped into a project, it has to be compiled, using the same C++ compiler as your project. It didn't seem to like the particular compiler used by DynRPG (and DynRPG has to be picky about it because it's a hack of memory addresses in RPG_RT.exe). I also tried Easylogging++, and with that one I was able to get it working with the default configuration, but for some reason it had trouble when I tried a custom configuration.

At any rate, these libraries didn't have the indenting trick I wanted, so I figured I'd have to write a simple logging class of my own. I ran into an issue while trying to write functions for that class, though: functions need to know what type of variables are being given to them as arguments. Up until then I'd been using statements like
*ofDebug << debugIndent << "Current value: " << value;
and that worked great because the << operator could handle pretty much any kind of variable without fuss. Even if all my function really did was a single line of code similar to that, I would have to turn the message into a single string before passing it in, or something of that nature.

Fortunately I recalled that C++ supports a somewhat more arcane method for this sort of thing: function-like macros. I haven't really had much use for them before, but they came in handy here. Basically I was able to define a pattern such that the pre-compiler will literally substitute in something along the lines of the above code whenever it sees
LOG_OUTPUT("Current value: " << value);
and then the compiler will work with that instead. Since it's a literal hard-code substitution there's no worries about the types of variables used or how many pieces go into the message. I made similar macros for starting and ending functions which not only write the function name to the debug file, but take care of increasing or decreasing the indent. Now if I decide to change how they work, I don't have to change the code in dozens of places, just one.