Here is the 7DRL submission on Itch.io. Here is the latest version on Github.io.
Long ago I spent a miserable year in graduate school. The research assistant job I had before I dropped out was in the cancer wing of the university's hospital. The radiation treatment facilities were adjacent and I'd gotten a tour of them when I started my job. It was a row of rooms with twisty entrance passages to break the lines of fire.
My parents came to visit me shortly after I had dropped out. I took them to see where I had been working. It was a Sunday and the radiation wing was largely deserted. Eventually, though, we were confronted by a woman who said "I don't think you should be in here!" and threatened to summon security. I hustled on out of there, chagrined. It really drove home that I no longer belonged at the school.
This feeling of being accosted where you don't belong was what I had in mind for this year's 7DRL challenge. I played the HITMAN reboot games recently and enjoyed the disguise mechanics. My primary goals for this year were:
- Produce a web-playable game
- Experiment with disguises in the framework of my existing thief roguelike game
Getting a web-playable game took about half the time. I was using languages, platforms, etc. that I haven't really worked with before. Working on the disguise mechanics took the other half. I don't know that I've succeeded in making a really fun disguise system yet, but there is a fair amount that went into it.
All the new tech:
Rust is not bad. I'm not sure yet if it's where I want to write all my code going forward, but it isn't bad. The compiler gives good error messages, and the game seemed to perform adequately. I didn't do any profiling. I did run into one crazy problem with the compiler; it doesn't properly handle excluding library features on a per-platform basis. I asked on a forum and the nightly build has a fix for it. In the end I just targeted WebAssembly alone; I haven't got a native target. My framework is simple enough that I expect I could write a Win32 version of it fairly easily in Rust.
WebAssembly still feels half-baked. I had trouble with wasm-bindgen versioning, so I ended up just wiring up the imports and exports myself. I stuck to simple integral data types in the function parameters and didn't try to do any memory sharing.
Javascript is also not bad. It always seems to work pretty much the way I expect it to. I only wrote around 450 lines of Javascript for this project.
WebGL is very similar to OpenGL. It works okay. I'm not a huge fan of the OpenGL way of doing things, but I am familiar with it so that helped.
Github.io was new to me. It turns out to be a really great way to set up a static website. Just point a Git repo at it and away you go. I'm told you can set up Github actions to automatically build the site when a repo over on Github changes. I'll probably try to set that up; I ended up manually doing that step and it was getting annoying.
The new game design elements:
Since the player's thief can look like the enemies I added a little overhead caret to mark him. I added bump-to-interact functionality (for changing clothes) which wasn't in the previous game. (It was in the first ThiefRL so I referred back to that.)
I created two different colors of guards, in order to have two different disguises (plus your default outfit). I set it up so one class of people is not allowed in the private rooms of the house; if the private-wing denizens see that outfit they'll attack. The public area is patrolled by both the public and the private guards. I'm not thrilled with how this turned out; bifurcating these already-small levels results in more un-patrolled space, since guards try not to go into a room where they will have to go back out via the same door. I have thought about changing the patrolling behavior to allow for going into dead ends; maybe they would stop and stand for a bit. Haven't gotten to that yet though.
Guard awareness got some adjustments. Since you are in disguise they can't just attack you, which means you can be doing things in their view like picking up loot or climbing on tables and that looks weird. When the player does anything "suspicious" it sets a flag for the next guard update. If they see the player, and the player is being "suspicious" then they escalate. In the old thief game if you got spotted you could duck into a bush or under a table in full view of the guard and hide successfully. This is no longer possible. I felt like I needed to nerf hiding somewhat to make the disguises serve more of a purpose.
Once I hit on the idea that disguises would effectively cut guards' maximum distance they can see you at down to one or two squares it was pretty fun to try to maneuver around them in the rooms to avoid being too close. Right at the end I realized that the inner-room disguise was strictly better than the outer-room disguise, which was not very fun. I ended up making it so that people who match the disguise are not as suspicious as people who don't. It doesn't make a lot of sense logically, but it means you want to be wearing the outfit that matches the area you're in (and the people who are in it) which gives a reason to switch back and forth. It's still not much of a reason.
I experimented with having special "boss" guards who could see through disguises from a distance. This was an idea borrowed from Hitman. It complicated things too much, I felt, so I removed it.
For a while I disallowed hiding in bushes or under tables (or underwater) while in disguise. This is potentially interesting; it gives much more of a mode shift between running around in the thief outfit and wearing a disguise. It means the thief outfit has its own perks and isn't strictly inferior to the disguises. I took it out because I felt like it was complicating the rules. It also made for some really difficult maneuvering sometimes in the current levels. It's worth further consideration though.
I made the one-way windows so the player can see through them both ways. I'd tried this out on the original thief game and rejected it because I didn't want players to feel like they had to run around the house to peek in all the windows and uncover as much of the map as possible before going in. However I think this is a really positive change. One of my big design tenets is that you should have areas you can see but not get to easily and this serves that goal handily. Often you'll go past a window and see a disguise in the room on the other side and it gives you a goal to work toward.
Placing the disguises so it will be satisfying to find them is something I haven't really fully worked out. Right now they're placed toward the back of their respective zones, so you will have to move through at least some of the zone without the benefit of its disguise. I really would like there to be more of a sense of accomplishing something when you get to a disguise, though.
Overall it was not my strongest game but it should hopefully be at least somewhat fun. Disguises make things easier, and they give you more detailed interactions with guards. Both of these present challenges to keeping the game fun. I think there are lots more things that could be done with disguises though. A couple ideas I wanted to try:
- Identify a particular guard who is a secret ally. To do this you need to see the faces of guards from close range; they'll get marked off as they're identified as either your ally or not.
- Confront a particular person when none of the other guards are nearby.
- Disguises that provide environmental protection (from cold, or dust storms, say)
- Ways to influence the patrolling behaviors of guards. Could be by activating "activity stations" that will occupy a guard for a time (cleaning up a mess or something). Or it could be by opening and closing doors, and guards would assume that closed rooms (that aren't on the main path) don't have to be checked but open rooms should be checked.
- Add stationary guards; "bouncers" to make it much harder to get into parts of a level without the right disguise.