ZScript mixins

From ZDoom Wiki
Jump to navigation Jump to search
Note: This feature is for ZScript only.

ZScript mixins are similar to D's template mixins, which may contain a variety of data. They contain code that can be reused in several places without duplicating it.
Mixins currently can only be used for classes, and cannot be used across translation units.
Multiple mixins can be used per class as well.

Usage

Mixin definitons must always be defined in the global scope - that is, outside any classes or structs.
A mixin definition must specify what it will be used in and a name for the mixin. Currently, the only usage type supported are classes.

Examples

A simple example for inserting a mixin into classes.

mixin class Foo
{
    int aNumber;
    void SetMyNumber (int num)
    {
        aNumber = num;
    }
}

class Bar
{
    mixin Foo;

    void AFunction ()
    {
        aNumber = 2;
    }
}

class Baz : Actor
{
    mixin Foo;

    Default
    {
        +NOINTERACTION
    }

    States
    {
    Spawn:
        TNT A 1 NoDelay
        {
            Console.Printf ("Before, aNumber is %d", aNumber);
            SetMyNumber (10);
            Console.Printf ("After, aNumber is %d", aNumber);
        }
        Stop;
    }
}

This is an advanced example, including actor flags, properties constants, states and more:

class TestActor1 : Actor
{
    int foo;
    mixin MyMixin;
    int bar;

    override void Tick ()
    {
        foo++;
        bar = EnumConst_C;
        Console.Printf ("foo: %d, bar: %d, baz: %d, actorPtr: %d", foo, bar, baz, !!actorPtr);
    }
}

class TestActor2 : Actor
{
    int foo;
    int bar;
    mixin MyMixin;

    Default
    {
        +TestActor2.MYFLAG
    }

    States
    {
    Spawn:
        BAL1 A 1;
        Loop;
    }

    override void PostBeginPlay ()
    {
        Super.PostBeginPlay ();
        bar = 1;
        actorPtr = self;
    }

    override void Tick ()
    {
        foo = EnumConst_B;
        bar *= 2;
        Console.Printf ("foo: %d, bar: %d, baz: %d, actorPtr: %d", foo, bar, baz, !!actorPtr);
    }
}

mixin class MyMixin
{
    enum MyEnum
    {
        EnumConst_A,
        EnumConst_B,
        EnumConst_C,
    };

    Actor actorPtr;
    int baz;

    Flagdef MYFLAG: baz, 0;

    Default
    {
        +SOLID
        +ISMONSTER
        // Can't set MYFLAG here, as it'll have the class' identifier and we can't know that in advance.
    }

    States
    {
    Spawn:
        TROO A 1;
        loop;
    }
}

This simple, concrete example replaces the imp and baron spawn states with TNT1A0 for some jumpscare fun:

mixin class JumpscareMonsterMix
{
    states
    {
    Spawn:
        TNT1 A 10 A_Look ();
        wait;
     }
}

class MixImp : DoomImp
{
    mixin JumpscareMonsterMix;
}
 
class MixBaron : BaronOfHell
{
    mixin JumpscareMonsterMix;
}

See also