Creating a Custom Profile

Overview

This guide will very quickly show you how to setup a custom profile which can be used when loading replays.

It will introduce only the very simple fundamentals of how to edit certain aspects such as item names.

Setup

Hot reloading is supported, so it is recommended to keep the viewer open as you make changes for immediate feedback.

First locate your profiles folder in path_to_viewer\resources\app\assets\profiles :

Make a copy of the template folder and rename it however you like:

In the viewer, this profile should immediately become available:

You can now switch to this profile and load a replay!

Editing the Profile

To edit the profile, open its folder. You should find an includes.js file and a datablocks folder:

includes.js is a simple script which imports all the required functionality from the vanilla profile. This includes, but is not limited to:

  • The vanilla parser - Handles parsing of the replay file

  • The vanilla renderer - Handles rendering of the map, static items etc...

  • The vanilla datablock system - Handles data blocks for customising vanilla features

  • The UI - Playback seeker, Info side bar etc...

The datablocks folder is what you will be interacting with the most as it contains 99% of whats needed to the majority of custom rundowns.

Within the datablocks folder you will find the following:

  • stickfigure.js - Contains model data for whats used for each part of the stick figure models

  • gear - Datablock information for gear parts and gear

  • items - Datablock information for items (heavy items and consumables)

  • enemy - Datablock information for enemies

A Quick Example - Changing the name of Strikers

To change the name of a striker, lets navigate to datablocks/enemy and open the enemy.js script:

const { EnemyDatablock } = await require("../../../vanilla/datablocks/enemy/enemy.js", "asl");
const { Identifier } = await require("../../../vanilla/parser/identifier.js", "asl");
const { BigFlyerModel } = await require("../../../vanilla/renderer/enemy/models/bigflyer.js", "asl");
const { FlyerModel } = await require("../../../vanilla/renderer/enemy/models/flyer.js", "asl");
const { HumanoidEnemyModel } = await require("../../../vanilla/renderer/enemy/models/humanoid.js", "asl");
const { SquidModel } = await require("../../../vanilla/renderer/enemy/models/squid.js", "asl");

EnemyDatablock.clear();

const shooterScale = 0.8;

EnemyDatablock.set(Identifier.create("Enemy", 0), {
  name: "Unknown",
  maxHealth: Infinity
});

EnemyDatablock.set(Identifier.create("Enemy", 20), {
  name: "Scout",
  maxHealth: 42,
  model: (wrapper, enemy) => {
    const model = new HumanoidEnemyModel(wrapper);
    model.applySettings({
      parts: {
        head: {
          type: "Shooter"
        }
      },
      headScale: {
        x: 1.3,
        y: 1.3,
        z: 1.3
      },
      armScale: {
        x: 1.1,
        y: 1.1,
        z: 1.1
      },
      scale: enemy.scale * shooterScale
    });
    return model;
  }
});

// ...

As you can see, various enemies are defined by setting their ID and properties to the EnemyDatablock .

An enemies ID is the persistentID of the enemy type as determined by the datablocks used in-game. More information about this can be found on the official docs.

Navigate to the Striker definition:

const Striker = {
  name: "Striker",
  maxHealth: 20,
  model: (wrapper, enemy) => {
    const model = new HumanoidEnemyModel(wrapper);
    model.applySettings({
      scale: enemy.scale
    });
    return model;
  }
};
EnemyDatablock.set(Identifier.create("Enemy", 13), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 31), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 32), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 24), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 49), Striker);

The game uses multiple types to represent strikers, thus it has to be defined multiple times.

You can now change the name of the Striker to something else, and when viewed in the viewer you should be able to see the new name you applied:

const Striker = {
  name: "Not Striker", // <--
  maxHealth: 20,
  model: (wrapper, enemy) => {
    const model = new HumanoidEnemyModel(wrapper);
    model.applySettings({
      scale: enemy.scale
    });
    return model;
  }
};
EnemyDatablock.set(Identifier.create("Enemy", 13), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 31), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 32), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 24), Striker);
EnemyDatablock.set(Identifier.create("Enemy", 49), Striker);
You will need to enable "Show Enemy Info" in the viewer settings

For information about each existing datablock and its properties, see the docs here.

Last updated