Portfolio

This website was created with the aid of ChatGPT.

Projects

I almost always have at least one ongoing project. A few of my more-or-less completed projects are listed below.


Curse of Strahd

First Exposure

In my early days as a Dungeon Master, I decided to run Curse of Strahd simply because it seemed like a very complete module. It had maps, characters, a plot, magic items, intriguing areas, and juicy backstory options. The problem was that no matter how many times I started a campaign, it fizzled before anyone could get to the castle, which is sort of the entire point of the module. I finally decided that I was going to run a game of Curse of Strahd on Roll20 every Sunday, with or without players, and we were going to make it to the castle one way or another. Luckily, I had a lot of interested parties. Six people showed up for session one. Several players fell away by session two, leaving me with two wonderful players who committed wholeheartedly to the schedule and to the campaign. They found a third who rounded out the party, and a fourth came from one of my other campaigns as a pop-in/pop-out player. It took us two years to get to the castle. I learned many important DMing lessons on that first major campaign. The campaign, like all of my DMing, is entirely text-based, so the chat log represents a complete view of the entire adventure, minus whatever chatting we did via Discord texting. Interested readers with too much time on their hands can find the logs Here.

The Problem

5th Edition Dungeons and Dragons has a lot of great campaign modules, but my personal favorite is Curse of Strahd. The castle which serves as the final dungeon in the campaign is notorious for its complexity and its many layers. Unfortunately, tabletop roleplaying is often limited to two dimensions, which means that each floor must have its own map. This works well enough for the most part, but occasionally I have encountered situations where it proved very detrimental to the immersion. If the players are having a combat encounter on the four-story spiral staircase at the heart of Castle Ravenloft, one should not have to switch back and forth between whole maps just to go up and down by a floor. Roll20 in particular makes this difficult to manage, because its native behavior is to keep all the players on the same map. I have come up with two different solutions to the problem. Both projects were interesting learning opportunities, and each has its own advantages.

Solution 1

Curse of Strahd comes with a beautiful set of isometric maps of the entire castle, complete with all floors. Unfortunately, this does not play well natively with Roll20, and it is confusing to use for in-person play. I wanted to have a way to present my players with a clean doll-house view of the castle, so they would have a better sense of the layout and the connections between the different areas. My first solution to the problem emerged from my recent exploration of Unity. I have a lot of experience with various 3D and 2D game development environments and modeling programs, so it wasn't too difficult to slap something together. I could have coded the interface myself, but I found it more expedient to make ChatGPT do it, since the code isn't particularly complicated. You can view the project here.

Solution 2

The second solution I came up with was a little more useful. I decided to write a Roll20 API script that would allow me to quickly shift between layers without having to switch maps. Because Roll20 does not have support for art layers, aside from its own limited "GM" "Map" and "Objects" layers, the script shunts everything that's not on the current "floor" to the GM layer, making it invisible to the players. In Roll20, tokens can have three numbers associated with them: bar1, bar2, and bar3 (so called because, when one of these numbers is fractional, it becomes a bar). Most DMs use Bar1 to present the HP of a given token, and Bar2 is often used to present a token's AC (with whole numbers). Bar3 (the red number) most often goes unused. The script tracks the whole number value inside every token's Bar3, and if a token's Bar3 value matches the current "floor" the script puts said token onto the Object layer, making it visible. With this script, the DM can quickly switch between multiple floors, moving all tokens appropriately. The raw script is Here.

The script in action:


Waterdeep, Dungeon of the Mad Mage

Dungeon of the Mad Mage is a ~30 floor megadungeon packed with interesting characters and monsters. While I can take no credit for the dungeon itself, I did create a particularly inventive way to handle a certain optional Beholder combat.

As every nerd knows, a Beholder is a very powerful monster with many eye-stalks, each capable of shooting off a magical ray with a different effect. Traditional beholders have about 12 eye stalks. My version of Xanathar had 32. While I won't list them, because the campaign is ongoing and the players have not yet had a chance to use all of the eyeballs they scavenged from Xanathar's corpse, I will talk about how I designed the arena for the battleā€”or rather, how I made the existing arena usable.

Skullport is a large underground shanty town of criminals and castaways. It also happens to be the one place in the dungeon with direct access to Xanathar's lair. Rather than have my players fight Xanathar inside his lair (where they would have either made the encounter trivial in close quarters or been obliterated by the whim of the dice, without a chance for strategy to come into play), I decided that it would be more appropriate and more entertaining to have them fight the beholder inside Skullport itself.

This presented a problem. Skullport is a three-story shanty town. It is large in all three dimensions. It is also criss-crossed by walkways and bridges which should obscure line of sight, which is very important when fighting a beholder. The designers of the module had not anticipated a large fight breaking out inside the town, which was obvious from the layered design and the fact that the place is laid out across three different maps that don't actually overlap all that well.

"But wait," I hear. "You've forgotten the Sargauth Enclave." In my rendition of Skullport, they were allied with Xanathar, and acted as the first wave of combat. Thirteen flameskulls is a fairly deadly encounter for the unprepared party, but because of the winding streets and plentiful cover sources, my party trounced them easily.

In order to make Skullport into something that began to think about considering the idea of potentially starting to resemble something that might almost be playable, I had to dissect it. I had to cut it apart, make its layers transparent, stack them up, split them apart, and really understand them.

I used a two-pronged solution. First, I implemented the Roll20 script mentioned above in my Curse of Strahd game (Solution 2). Second, I imported the modified images of the map into Blender as planes, got them all aligned properly, imported them into Unity, and did some magic.

With the help of ChatGPT, I created a monstrous abomination: a Unity WebGL game that would run on my server, using data ripped from Roll20 by a custom-made Firefox extension to plot the position of every token on the Roll20 map in three dimensions. This hideous thing allowed me to visualize the battle in 3D for myself and for my players. A custom Roll20 script would collect all the token data and push it to a Roll20 Handout in JSON format, where my custom Firefox extension would read it and send it to my server, where my Unity WebGL game could read it and apply it to the 3D version of the map.

The campaign has since moved on, of course; Xanathar is now dead. I consider the project a valuable mistake. Although everything worked as intended, it was clunky and my players did not enjoy it nearly as much as I had hoped they would. For the final two rounds of combat, I had Xanathar pull off a minor feat of magic, and teleport the party to an open arena where he would have the advantage.

Although now defunct, the project is available to view Here.


House of the Divided Mind

The year was 2018. Rolegate had just begun, and I was one of many early adopters. Rolegate is a platform for asynchronous play-by-post roleplaying games. After a few minorly successful excursions as a dungeon master on that site, I decided to try a new experiment: a Dungeons and Dragons campaign with 100 players. Rolegate proved a useful platform for the idea, and I soon had about forty players working alongside me to create a magical experience: a living, breathing Dungeons and Dragons world. Rolegate was wonderful, but it was also new and very much under development, and after one too many frustrating glitches in the system, we decided to migrate to something more stable: Discord. We developed the game into a West-Marches-Style Campaign world, with about ten DMs under one GM. A ridiculous campaign emerged, with dozens of smaller stories circling around one main one. I learned so many things from this experience that it would be impossible to list them all. I have an archive of the entire campaign Here.