← Back

Contents :: CrimsonZamboniDeathmatch Mission Customization Guide 🔗

Introduction 🔗

This guide assumes that you are already familiar with Enforce Script Syntax.

Many functions documented in this guide take vector instances as parameters to describe X, Y, and Z coordinates on the map. These instances can be expressed as either vector literals, which look a lot like strings, or as explicit instantiation, which look more like traditional C++ or C# syntax. Both are valid. Literals require less typing, but explicit instantiation might provide better syntax highlighting in your editor.

// vector literal
vector pos1 = "1234.56 7.890 4433.22";

// explicit vector instantiation
vector pos2 = Vector(1234.56, 7.890, 4433.22);

Note: For brevity, vector instances will be expressed as literals for the remainder of this guide.

Mission Hooks 🔗

The deathmatch mod provides mission hooks for executing code when rounds start and end. See the init.c files in the mission folders.

class CustomMission : MissionServer
{
    override void OnRoundStart(DMArena arena)
    {
        // Put your custom round start stuff here
    }

    override void OnRoundEnd(DMArena arena)
    {
        // Put your custom round end stuff here
    }
};

DMArena Interface 🔗

The following describes the public interface of the DMArena class that is usable after the CustomMission has been constructed.

class DMArena
{
    // Return the arena name
    string GetName();

    // Return the distance from the arena center to a position
    float DistanceFromCenter(vector position);

    // Return the playable radius of the arena
    int GetRadius();

    // Return the radius at which players are insta-killed for being too far away
    int GetKillRadius();

    // Find objects that need to be cleaned up at the end of the round
    void FindObjectsToClean(array<Object> objects);

    // Return true if the arena is dark and requires Night Vision Goggles
    bool IsDark();

    // Return possible player spawn points
    TVectorArray GetPlayerSpawnPositions();

    // Return a randomly selected player spawn point
    vector GetRandomPlayerSpawnPosition();

    // Set a player's location to a random spawn point
    void SpawnPlayer(PlayerBase player);

    // Return possible spawn locations for crates
    TVectorArray GetCratePositions();

    // Return true if at least one possible infected spawn location exists
    bool HaveInfectedPositions();

    // Return the number of possible infected spawn locations
    int GetInfectedPositionCount();

    // Return possible infected spawn locations
    TVectorArray GetInfectedPositions();

    // Return a random infected spawn location
    vector GetRandomInfectedPosition();

    // Return spawn locations for Christmas trees
    TVectorArray GetChristmasTreePositions();

    // Return true if playerCount is between the minimum and maximum player settings
    bool SupportsPlayers(int playerCount);
}

Arena Customization 🔗

See the Arena Customization Guide if you would prefer to customize arenas using JSON instead of Enforce script.

Arenas for each map are defined in the server mission init.c script. By convention, each arena is defined inside its own function and a CreateArenas function calls each of the individual arena creation functions before the server finishes loading the mission.

Creating arenas after CustomMission has been constructed and modifying arenas after they have been added to the DMArenaRegistry may result in undefined behavior.

Required Settings 🔗

All arenas must have names and center positions. Names should be strings that uniquely identify the arena location. Center positions should be vector instances. Construct a new instance of DMArena with these two parameters to start creating a new arena. For example:

DMArena arena = new DMArena("Mordor", "1234.56 7.890 5556.32");

After creating a new DMArena, it needs to be added to the DMArenaRegistry so that it can be used by the server. Call AddArena to add the arena to the registry. For example:

DMArena arena = new DMArena("Mordor", "1234.56 7.890 5556.32");
// ...
DMArenaRegistry.AddArena(arena);

Arena Radius 🔗

By default, arenas have a playable radius of 500 meters. If players travel more than 500 meters from the center point, they will begin taking damage. If they travel too far, they will eventually be insta-killed.

To change the playable radius of an arena, pass the desired radius as the optional third parameter to the DMArena constructor. For example, the following sets the playable radius of the Mordor arena to 250 meters:

DMArena arena = new DMArena("Mordor", "1234.56 7.890 5556.32", 250);

Note that as the radius increases, end-of-round object cleanup will take longer. Arenas larger than 500 meters are possible but generally not recommended as they may introduce stuttering when rounds end.

Rectangular Arena 🔗

By default, arenas are defined as a circle with a given radius. Rectangular arenas may be created with a specified width and breadth. The boundaries of rectangular arenas are aligned with the map's X and Z axes.

To make an arena rectangular, pass the desired width and breadth to the SetRectangle method. For example:

arena.SetRectangle(400, 200);

Player Spawns 🔗

Although optional, a sufficient number of player spawn positions should be set to ensure that players do not spawn on top of each other at the start of rounds. To set the possible player spawn positions for an arena, call the SetPlayerSpawnPositions method and pass a TVectorArray instance. For example:

arena.SetPlayerSpawnPositions({
    "4567.89 1.234 9876.54",
    "4433.24 2.872 9798.44",
    "4599.16 1.598 9811.59",
    // ...
});

If no player spawn positions are set, all players will spawn at the center of the arena.

Minimum Players 🔗

To prevent an arena from being randomly chosen when there are too few players connected, call the SetMinimumPlayers method and pass the minimum number of players required to randomly choose the arena. For example:

arena.SetMinimumPlayers(5);

By default, the minimum player count of areas is 0.

Maximum Players 🔗

To prevent an arena from being randomly chosen when there are too many players connected, call the SetMaximumPlayers method and pass the maximum number of players required to randomly choose the arena. For example:

arena.SetMaximumPlayers(20);

By default, arenas have no limit to the number of players.

Dark 🔗

Configuring an arena to be "dark" instructs the server to spawn players with Night Vision Goggles, even if the world time is set to daylight hours. This can be useful for creating arenas in underground locations on modded maps that make underground locations dark. For example:

arena.SetDark();

Walls 🔗

Walls enclosing arenas can be disabled on a per-arena basis. For example:

arena.DisableWalls();

See CrimsonZamboniDeathmatch Setup Guide: Disable Walls for a way to globally disable walls on all arenas.

Crate Positions 🔗

Crates containing high-tier items can be configured to spawn at random locations by calling the SetCratePositions method and passing a TVectorArray instance. For example:

arena.SetCratePositions({
    "4567.89 1.234 9876.54",
    "4433.24 2.872 9798.44",
    "4599.16 1.598 9811.59",
    // ...
});

Note: No crates will spawn if there are no spawn locations set.

Infected Positions 🔗

Infected can be configured to spawn at random locations by calling the SetInfectedPositions method and passing a TVectorArray instance. For example:

arena.SetInfectedPositions({
    "4567.89 1.234 9876.54",
    "4433.24 2.872 9798.44",
    "4599.16 1.598 9811.59",
    // ...
});

Note: No infected will spawn if there are no spawn locations set.

Christmas Tree Positions 🔗

When Christmas is enabled, Christmas trees can be configured to spawn by calling the SetChristmasTreePositions method and passing a TVectorArray instance. For example:

arena.SetChristmasTreePositions({"7878.65 432.12 10519.46"});

Unlike the other methods that take TStringArray instances, described above, Christmas tree positions are not randomized. Instead, a tree will spawn at every vector in the array. Very large arenas might benefit from having multiple trees, but I prefer to only have one tree per arena.

Note: No Christmas trees will spawn if there are no spawn locations set.

Props 🔗

To spawn a static object inside the arena when rounds start, call the AddProp method with the object type name, position, and orientation. For example:

arena.AddProp("Land_Wreck_C130J", "7878.65 432.12 10519.46", "-161.993 0.5 6.5");