The Road to Early Access basically looks like the Road to El Dorado, except the musical numbers are worse. Right now I am still in a land where I have to actually sit down and do all the stuff I’ve been putting off for the course of the product. Two things that fall into this category are “putting modules in the corner of a building” and “interrupts.” Oh, and “fixing the memory leaks.”
Putting modules in the corner of a building has been something that, since the start of the project, would blow up the game. There were a number of things causing problems here: first off, the code to actually handle the case of inserting the small “module footer” that forms the foundation of a module was blowing up if you put it in the corner of a map. This has been fixed. Second, when we finished a module’s foundation, we would delete the edges on the floor plan, and merge the leftmost and rightmost edges together. Obviously, this is not the right thing to do if a foundation piece is at the leftmost, or rightmost, edge of a blueprint – you end up collapsing two edges together that are at 90 degrees. So this has been fixed for the outside of modules. The inside of modules still breaks, because there is some funny business going on with how we construct interiors that I have yet to track down – but we’re making progress on long standing issues.
Interrupts are a bit more significant: the notion that a character, while doing a task (“haul goods to stockpile”), can be interrupted because some other job (“not being on fire”) takes precedence. This turned out to be not so bad to implement: every frame, we look at all the jobs that have a higher interrupt precedence than my current job and that are mandatorily evaluated. If a job has a higher interrupt precedence AND a higher utility, we abort the current job and go on to the next one. The bigger problem here is the problem of aborting the current job cleanly, which has meant going through the codebase and annotating everything to make sure it cleans up nicely. This has led to us fixing a plague of random crashes caused by, say, posting a job to harvest a cabbage because it was interrupted, despite the cabbage already having been harvested.
Finally, there is the issue of the memory leaks. We were leaking memory like a stuck pig, and this is going to get technical. Last night I threw a wobbly, for lack of a better term, and started poking about in the code base. I tracked the following memory leaks down by virtue of “disabling stuff and seeing what happens”:
- particle systems were not cleaning themselves up correctly, and were leaking memory on deletion (fixed)
- gossipping characters would leak memory due to a base class not having a virtual destructor (and several variations on the theme of “a base class not having a virtual destructor”)
- memory allocated during a range-based for loop in the pathfinding code would not be released correctly when we performed an early-out: this might be a MSVC bug or simply something about the C++11 spec I don’t understand, I don’t know, but it looks like calling return to abort a function from within a range-based for causes memory to not be freed from the heap. Which is odd.
- We never stored that a skin for the user interface was loaded after we loaded it, so we re-loaded all of the UI art every time we needed to draw a new UI widget. This got very bad, again, when gossipping characters needed an icon and we’d immediately load an enormous texture.
At this point, pausing the game thread has a perfectly consistent memory footprint from frame to frame: the renderer is, seemingly, leak-free. Turning on the game thread results in a game that does not leak memory until some time in Day 2 of the simulation. I decided I needed a better tool to figure out where memory leaks were coming from, and I found it in GlowCode, a handy piece of software that I’ve never heard of. If you are the sort of person tasked with optimizing things and fixing memory leaks, add GlowCode to your shopping list alongside Telemetry by RAD Game Tools. It is amazing – point it at your software, profile it in real time at an interactive (ish) framerate, and see memory leaks, in real time, as you run your software. I am a convert, and they are getting my money.
(On a side note: the gold standard for this used to be Rational Purify, now owned by IBM. Attempting to download a free trial of Purify from IBM resulted in an error page, repeatedly, until I somehow found a download for the EXE by just plugging “Free Trial Rational Purify” into Google until it returned the correct link; at this point, I discovered that they do not support Microsoft Visual C++ 2012 or 2013. Does anybody know why IBM hasn’t died yet?)
GlowCode pointed me at the next error that I hadn’t figured out: there is a very large memory leak in our code to handle events, which not only triggers every frame but seemingly has something to do with a large block of code labelled “FIXME”, and I cannot figure out, for the life of me, what it does. I will probably just delete it. We also have a smaller memory leak allocating memory from grid positions when sending data from one Lua game object to another, but I’m going to leave puzzling that one out to Micah.
For those interested, here is an internal changelog for the upcoming Revision 21. This is basically a summary of all the work that we have done this week, so you get some idea of how much we can get done in a week.
- FIXED: when paperwork, sweeping, and butchering are interrupted, the temporary tool is properly disposed of
- “chop planks” uses carpentry icon
- Buildings now have more or less consistent interior wall-top fill textures
- we now have a series of smaller gibs to go along with the larger gibs
- added dev button to spawn a bottle of whisky
- added proper icon for hunting job
- added in special fishperson melee attack animation
- hunting job now has an icon
- FIXED: “Interrupted Tidy Shop to Do Paperwork”
- FIXED: Crashing game opening work crews
- FIXED: Middle class single beds def had an extra space which removed them from game.
- bigger booms added to SK grenade attack
- FIXED: death of animals no longers triggers tragedy music (as tragic as it may be to us vegans -dgb)
- butchery spawns gibs (now we need a good way to clean these up)
- FIXED: “nullMessage” crash when a job destroys an item then restarts the job (I hope?)
- FIXED: steam knight now operates again
- FIXED: modules can now be placed on the corners of buildings, and the exterior of the building will render correctly. (The interior will still be broken; however, it is Harmless and affects Only the Visuals. Still working on this.)
- Enormous, nine-stage animation pipeline for stew and bread preparation
- FIXED: butchering crash
- FIXED: “Return XYZ” to Stockpile Spam in jobs panel
- added “spawn aurochs” dev button w/ cute icon
- butchering now uses hunting knife (and improved? animation timing)
- sounds attached to various tool use animations
- made gamestart way less generous
- FIXED: cannibalism now requires a HUMAN corpse, not any corpse
- color of MC single bed adjusted slightly
- LC cot is now 3×1 module, not 2×1 module
- fishpeople get special attack animation
- FIXED: memory leak in particle system
- FIXED: memory leak in animation system
- FIXED: memory leak loading skins
- FIXED: memory leak in pathfinding system
- FIXED: basically, just memory leaks
- removed “nuts” and “screws” from workcrew name text list because, although hilarious, we’re not in the business of double entendres
- FIXED: death now aborts FSMs; should help with characters getting stuck due to melee combat w/ dead entities
So, yeah. Productivity. The next thing to do – for me, at least – is to finish the save game code. Those of you who have played Dungeons of Dredmor know that save games are, shall we say, my Achilles heel – and a very hard problem in general. Hopefully we don’t have the same hideous problems that we had with Dredmor’s saves – the one lesson I learned from Dredmor is “make your save game format not binary.”