Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

The ZDCode Booth!

Recommended Posts

As some of you may know (and the rest now will), ZDCode is a language intended to replace DECORATE, by supplying several abstractions intended to make the ZDoom/Zandronum modder's life a bit less painful. Supporting any DECORATE version released after around 2014, give or take, it allows for elaborate constructs, with simple tools and building blocks, including:

  • Pretty state label logic!
  • Conditional flow!
  • Chances and repeats!
  • Almighty class templates!
  • Macros!
  • Parametrization!
  • Syntax that won't give you aneurysms!
    • And more!


So, that's why I ask you: what are your latest creations in ZDCode? I am really interested and curious to see what the Doom modder community is doing with it! (if you are, at all, which realistically you probably aren't lol ;-;)


Downloads, more examples, and more info at the ZDCode GitHub repository.

Here are a few examples to help you out already; CyberVice with the barrages, the Psychopath who underestimatingly taunts you, and the many flavors of fireball (including deathly mint and barbecue sauce).


class<translation, speed, damage> FireballFlavor extends DoomImpBall {
    set Translation to translation;
    set Speed       to speed;
    set Damage      to damage;

derive FireballRed    as FireballFlavor::("0:255=%[0.15,0,0]:[0.9,0.75,0.3]",     8,  40);
derive FireballYellow as FireballFlavor::("0:255=%[0.15,0.1,0]:[0.9,0.9,0.4]",    12, 30);
derive FireballGreen  as FireballFlavor::("0:255=%[0.1,0.2,0]:[0.4,0.9,0.2]",     14, 15);
derive FireballCyan   as FireballFlavor::("0:255=%[0.05,0.2,0.25]:[0.2,0.8,0.9]", 16, 30);
label Missile {
    CBVC E 4 A_PlaySound("cybervice/grunt");
    x 8 CBVC E 1 A_FaceTarget(10);

    x4 { // do this four times
        x 3 CBVC F 7 [bright] A_SpawnItemEx(
            random(4, 7) / 3, random(-1, 2), random(-3, 3),    // position
            random(3, 8) / 5, random(-2, 2), 0                 // velocity
            random(-50, 50),                                   // angle
            SXF_MULTIPLYSPEED                                  // flags
        CBVC E 3 [Bright] A_FaceTarget(15);
        sometimes 50 { // he doesn't like aiming alright...
            ifjump A_JumpIfTargetInLOS($offset, 30); else {
                // using "else" cleverly helps negate the check here!
                x 2 CBVC E 4 A_FaceTarget(25);

    CBVC E 8 A_PlaySound("cybervice/huff");
}; // you need semicolons after closing blocks, too... sigh

// ...but not after closing *class* (or class template) blocks... SIGH!~
label See {
    sometimes 20 // 20% chance
      	// like in C, you don't need curly brackets for everything
        ifjump A_JumpIfTargetInLOS($offset, 50) // $offset is magic; ZDCode interpretes it when this is compiled
        	// here neither
            TNT1 A 0 { // ...but you can use them to group multiple actions into one state
                A_Log("I see you!");

    // ...

Share this post

Link to post

Oh, also, v2.9.0 is out, with class groups and iteration and more.


class LaserGun extends Shotgun {
    set Weapon.AmmoType   to "Cell";
    set Weapon.AmmoUse    to 1;
    set Weapon.AmmoGive   to 30;
    set Weapon.SlotNumber to 6;
    set Tag               to "Laser Gun";
    set Translation       to "0:255=%[0.1,0.07,0.4]:[0.4,1.95,1.8]";

    set Inventory.PickupMessage to "$PKP_LASERGUN";
    macro MFire(mod) {
        from @mod inject FireLaser;
    macro MPrint(mod) {
        TNT1 A 0 A_PlaySound("zdpack/lasergun/select", CHAN_WEAPON, 0.6);
        from @mod inject PrintModule;
    macro CycleModule {
        for mod index i in group laser_modules {
            ifjump A_JumpIfInventory(mod, 1, $offset) {
                if (args[0] >= 0 && i > args[0]) {
                    TNT1 A 0 A_SetArg(0, -i);
        // Ha! No need for breaks or returns! Just be clever! :)
        if (args[0] < 0) TNT1 A 0 A_SetArg(0, -args[0]);
        else             TNT1 A 0 A_SetArg(0, 0);
        inject FindModule(MPrint);
    macro FindModule(defer) {
        for mod index i in group laser_modules {
            ifjump A_JumpIfInventory(mod, 1, $offset) {
                if (i == args[0]) {
                    inject @defer(mod);

    label Fire {
        SHTG A 3 A_GiveInventory("DefaultLaserModule");

        // fire!
        inject FindModule(MFire);
        SHTG A 4 {
            A_PlaySound("weapons/railgf", CHAN_WEAPON);

        // boring shotgun sequence...
        SHTG BBCCCBB 1;
        SHTG A  2;
        SHTG A  5 A_ReFire;
        goto Ready;

    label AltFire {
        SHTG B 6;
        inject CycleModule;
        SHTG B 3 [Bright];
        SHTG B 4;
        goto Ready;


Share this post

Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now