There are many ways to add randomized elements to a DooM map, such that monster/item placement, teleport destinations, or even the geometry itself is different each time the map is played. If you're targeting cl11 or cl21, the RandomJump, LineEffect and Spawn codepointers basically have all your bases covered. In contrast, if you're targeting cl2, your only option is monster behaviors. That is, mechanisms based around monster pathing or damage rolls. For the Boom-heads out there there's another viable source of randomness in the idle frame offsets that are applied to every map object the first time the map is loaded.

In order to prevent dormant enemies from idling in lockstep with each other, the game applies a random offset to the first state of each object. For example, consider a zombieman, with its 2 idle states each of which are 6 frames. Upon starting the map, the duration of the first state for each zombieman is reduced by random amount between 0-5 (the first state can never be skipped entirely). This applies to all objects, enemies, powerups, decorations, it's all the same under the hood.

So how to use this? One simple idea is to create a decoration object that exists as solid and blocking for a randomly-determined amount of time before poofing out of existence. So if you have, say, 4 voodoos scrolling down a closet, each blocked by one of these objects, they're 'competing' for who's blocker will randomly expire first, and thus which actions get triggered first. This can easily be adapted to shuffle items to random locations:

A more complicated implementation I came up with is to have these 4 voodoos, and then add a mechanic such that if they don't get unblocked by a certain fixed amount of time, then they stay permanently blocked. The result can be interpreted as a 4-bit binary digit, where a "0" is a voodoo that never got unblocked, and a "1" is a voodoo that got unblocked and was able to trigger its actions. I made a secondary mechanism to "interpret" the result, such that for each possibility 1 specific voodoo doll (out of the 16 total) would advance forward and the rest would not move. Here are some demo wads: rng_tests.zip

rng_test_1.wad - a simple item shuffler.

rng_test_2b.wad - a "1 out of 6" random chooser. uses the more complicated mechanism.

Note: these only work in cl9 and above, as cl2 rng is seeded and will give the same result every time.

GrainOfSalt and I used these mechanisms in our halloween maps this year in order to randomize weapon and key placements, but if you're reading this then you probably know that already: wormwood5.zip

JUMPWAD deh summary

Today I posted some MBF-compatible platforming maps made by myself and GrainOfSalt:


JUMPWAD: Download

There's quite a lot of Dehacked shenanigans in the mapset. Turns out when you completely remove the concept of weapons, ammo, health, and enemies from the game you have free rein to repurpose basically every mobj and their states for other mechanics.


(1) Jumping

The pistol is replaced with an infinite ammo weapon that fires a projectile which calls VileAttack and promptly kills itself. Because projectiles target the mobj that created them the attack hits the player, dealing damage and launching them into the air. To complete the illusion we give the player (effectively) infinite health and blank out all the HUD and pain palette graphics.

This is not a new trick, it goes back to at least 2014, possibly earlier. I don't think many people have designed around it because it basically requires removing the concept of player HP entirely.

The mechanics differ from normal jumping in that the player can fire the weapon while falling, jumping mid-air in a similar manner to how double jumps work in platformers. We treat this as a feature and have designed many gaps around the mechanic.


(2) Gems

The big collectable gems that count towards Kill% are actually immobile enemies with the MBF TOUCHY flag, such that when you make contact with them they get killed. This was coupled with MBF's LineEffect action in their death frames to create the "You need X gems to exit" mechanics.

Each gem has two variants: one that spawns on the ground and the other which spawns on the ceiling. Floating gems are implemented by lowering the ceiling to the desired spawn position in the editor, then having the ceiling raise back up in game when the level begins. Because gems are not affected by gravity they will remain at the altitude where they were spawned.

Pointless trivia: before we made the move to MBF we were trying to make everything work in Boom (well, before I got involved GrainOfSalt was actually trying to keep everything limit removing). The Boom-compatible gem pickup system I came up with at the time was very convoluted:


It used silent invisible enemies in closets constantly walking over teleport lines that were blocked by the gems in the level. When the player picked up a gem the destination is unblocked and the invisible enemy can teleport into the map where the gem once was. At this point it would immediately encounter another set of monster-only teleport lines which take it to another closet where it will walk over triggers to lower a sector in a voodoo closet, thus allowing us to tie arbitrary actions to any particular gem pickup. When the decision was made to shift to MBF I was happy to abandon this setup in favor of the much simpler TOUCHY/LineEffect version.


(3) Snow

Pretty simple: ceiling-spawning enemies that fire a constant stream of 0-velocity projectiles which are affected by gravity. They need to be awakened like normal doom monsters before they'll start firing, which is why each snowy level makes you do a few jumps before entering the main areas (quite convenient that jumping here is equivalent to firing a weapon!)


(4) "Jump Orbs"

The red floating sprites that launch you upward were pretty tricky to get right, and were the first major mechanic made for the project that required MBF codepointers. Here's a condensed summary of how they work:

- Lost Soul is replaced with the new sprite, and is given the SPAWNCEILING and TOUCHY flags.

- When the player touches Lost Soul it calls VileAttack in its death frames, launching the player upward.

- After a few moments, the Spawn codepointer is used to create a replacement orb object in the same spot as the original.

The Lost Soul is the only mobj that could be used for this purpose as its the only enemy that will not fall to the ground when killed. This was needed for them to stay in the air in the same spot each time they respawn.


(5) Meteors

Similar to their implementation in Wormwood ]|[, JUMPWAD has static meteor projectile obstacles which the player needs to avoid. (Though instead of doing damage to you, here they simply push you around).

They function using bouncy walls: meteor projectiles are spawned within a 242-affected sector which has scrolling actions applied to it, pushing it in some direction. The actual spawning is tied to the pain state of another mobj, such that the patterns and refire rates of the meteors could be controlled via voodoo closets.

The Wormwood ]|[ meteors were actually a bit more complicated: because that mapset also had normal doom monsters and combat we had to make some changes to prevent enemies from infighting with the meteor launcher mobjs. The meteor launcher in Wormwood spawns a meteor mobj, and when the meteor collides with something the meteor mobj itself fires an invisible projectile which calls A_Explode and does the actual damage. That way when an enemy is struck by a meteor, the meteor itself is seen as the source of the damage, not the meteor launcher, and because the meteor promptly kills itself after the collision the enemy turns its attention back to the player. Fun stuff!!!

To make my life easier I wrote some lua to generate all the necessary mechanisms automatically: https://github.com/ribbiks/doom_lua/blob/main/meteor_prefab.lua

Resource wad:

JUMPWAD resources and doombuilder configs can be downloaded here: rbkz.net/doom/jumpwad_doombuilder_cfgs.zip

I've seen the topic come up a few times about how mappers keep organized while making nonlinear doom maps, so I figured I'd share some of my layout scribblings I've made over the years. I'm a fan of drawing arrows and jotting down notes onto a screenshot of the layout while brainstorming routes the player might take through the level, generally after I have a basic outline of the map but before I've committed to any proper detailing. Examples:

FCFF MAP01:

FCFF MAP06:

WORMWOOD MAP02:

WORMWOOD_EU MAP04:

MAGNOLIA MAP31:

MAGNOLIA MAP03:

WORMWOOD ]|[ MAP03:

I've added some of my most commonly used lua scripts to a github repository. You can find them here: https://github.com/ribbiks/doom_lua

squarifier.lua

bevel.lua

Adds bevels to the intersection of all selected linedefs.

circularizer.lua

Transform a map from a rectangle into a ring.

flank.lua

Adds border linedefs to the interior of all selected linedefs.

join_identical_sectors.lua

Join (or merge) all selected sectors that have the same floor, ceiling, brightness, tag, effect, floortex, and ceiltex.

make242c.lua

Apply fake floor, ceiling, and colormap effects to all selected sectors.

select_overlapping_monsters.lua

Does what it says on the tin.

squarifier.lua

"Squarifies" all selected linedefs.

While clearing out one of my old folders of miscellaneous doom scraps I came across wallscroll.wad, a prototype for animating textures from one state to another based on a triggered action:



The way it works is outlined in this post. Each frame of the animation is stuffed into a single texture:


After hitting the switch a voodoo doll then rapidly scrolls the wall with the big texture 128 units at a time, simulating an animation.

download: wallscroll.wad

Teleport destinations are mobjs like any other, which means you can make them pushable, killable, etc, via dehacked flags. One simple thing you can do with this is boom-compatible teleporters with multiple destinations:



Download: teledest1.wad

If you walk over the teleporter it takes you to the red side. But if you hit the switch, the teleporter now takes you to the blue side instead.

When you walk over a teleport linedef the engine searches through all sectors (in ascending order) looking for one which matches the tag of the tele line and which contains a teleport destination object. The red telepad has a lower sector index than blue, so it is found first in the search. When you press the switch, the teleport destination object gets pushed off of the red telepad, so the search for a teleport destination continues onward to the blue one.

In the demo wad the destination objects are candle sprites so you can clearly see what's happening, but in practice you could blank them out with an empty graphic.

DoomBound 1

Back when Starcraft custom mapping was a thing there was a popular game type called "Bounding" that involved guiding small units through timed patterns of exploding obstacles. Think part puzzle-game, part rhythm game:



I had the terrible idea to try and create timed exploding obstacles in Doom (specifically, in boom-compatibility):


I cobbled together some dehacked, wrote very elaborate lua scripts to generate the explosion mechanics, and had a decent prototype going. It might be the most complicated voodoo-doll mechanics ever used in a map? Don't quote me on that.

Gradually my enthusiasm for the idea wore off. The explosions can feel pretty janky, and I imagined that very few people would actually be interested to play something like this (especially if I started making very challenging obstacles). Instead of having it rot on my harddrive though I figured I might as well post the tech demo: doombound01.wad (tested in prb+ complevel 9)

Some things to note:

- Each difficulty setting has different explosion patterns

- UV requires SR50