Introduction

It's possible for users to add custom sprites (animations made from pictures) to KeeperFX. Requires version 0.5.0 or newer.

Overview

Dungeon Keeper and KeeperFX use sprites from .dat files for all things in game, like Creatures, Objects, Traps and Projectiles. These are PNG images for every frame of animation, and when available, for each view direction too. The extracted images can be found here.

The custom sprites do not need to be merged into these .dat files, but can be bundled in .zip files, along with a json file that describe how these .png files make up the sprites.

Creating a Custom Sprite
Exporting the PNG files

Sprites in Dungeon Keeper can be as small as 32x32 (wooden barrel) or up to 128x128 pixels large (Hero Gate, big lairs).
Aim at roughly this target resolution when exporting your individual images.

PNGs will automatically be converted to Dungeon Keeper's limited palette.
Try to stay within Dungeon Keeper's limited range of colours. Otherwise, smooth gradients may turn into harsh cut-offs, or rogue pixels may stick out.
If there are issues, programs such as GIMP let you convert and clean up images manually. To import the DK palette into GIMP, use this file.

You should have images for both perspectives (top down and first person).
When not possessing a creature, players look down at the game world at a ~45 degree angle. Top down sprites need to be displayed at this angle too, the exact value is (360 * 266 / 2048). (This is easier by making a 3D model and rendering it from different cameras.)

Simple sprites like the barrel have only 1 rotation.
Their image will act as a billboard and always face the player.

But optionally, sprites can have multiple rotations. They change their image as you rotate your view, faking a 3D appearance.
You'll need 5 rotations: a view from the Front, Right Front, Right, Right Back, Back.
The naming convention is "front", "rf", "right", "rb", "back".
The left side is mirrored automatically.

For animations, the number of frames should be somewhere between 4 (basic lairs) to 12 (Dungeon Heart) or even 16 (spinning spell books and door keys).

Finding or Creating a Model

3D modelling programs like Blender can be used to take a 3D model to then render into images.

Dungeon Keeper's limitations make it simpler than it would be for a modern game:

Details (and small mistakes) will get lost when rendering at such small resolutions.
Texturing is very simple and flat colours will often do the trick.
Simple shaders (e.g. Blender's Toon BSDF, Glossy BSDF) fit better than modern realistic standards.
Light bounces should be set to (near) zero to emulate 3D rendering from 1997.

If you can't make one yourself, many websites such as https://opengameart.org/ offer models for free.

In Blender:

Change "Output Properties -> Output" to define the folder your rendered images will go in.
Keep 8-bit color depth checked.

Check "Render Properties -> Film -> Transparent" to export the sprite with no background.

In the Compositing tab, round transparent pixels. That way, pixels with at least 50% transparency are removed.
Dungeon Keeper sprites are sharp, with distinct outlines. Consider lowering "Film -> Pixel Filter -> Width" to limit blurring further.

Blender template:

Download an example file here

It has 10 cameras set up: 1 for each angle, 5 for each perspective.

I use the Multiple Camera Render plugin to select them all and render all 10 at the same time.

The Pixelate node group in the Compositing tab does 2 things:

  1. Limit the number of colours slightly (to 256) - for more noticeable bands of colours, and easier conversion later.
    Change the first Value in the node group to tweak this.
  2. Round transparent pixels
Creating the JSON file

A JSON file needs to be created to explain to the game how the different png images come together to form a sprite. The easiest way would be to take an existing JSON file from another sprite and modify it for your custom sprite. A json file can be made with any text editor, but using an application that can validate them is recommended, as it's easy to miss a bracket or comma and have the entire file not work.

Enter all the filenames of the images making up the sprite into the json file, following this format:

[ // opening square bracket, for the entire file, needs closing up.
{ // opening curly bracket for each sprite you put in the zip. A comma after each one except the final one.
  "name": "CUSTOM_SPRITE_NAME", //The name given here will be used to assign the sprite to an object. May only use capitals.
  "rotatable": [false],  //Set to either true or false, when set to false the first direction is the only one to ever be shown.
  "fp_offset_x": 24, // set these values to find the exact point where the sprite is set the object. Usually you want the bottom middle of the image.
  "fp_offset_y": 95, // The offset can be set per sprite, but also per file. Then add these lines at the "file" level.
  "td_offset_x": 23,
  "td_offset_y": 83,
  "fp": [ // After the configuration settings, add all the directions of first person sprites. The 'fp' name is required, and the square bracket needs closing and a comma.
    [ // Square bracket for each direction. Front, Front Right, Right, Back Right, and Back in that order. A comma after each one except the last one. Non-rotatable sprites need only one direction.
      { // The list of the files for this direction, each file is an animation frame. If there's just one, the object does not animate. Again close each curly bracket with a comma except the last one.
        "file": "banner3fpfront0001.png"
      },
      {
        "file": "banner3fpfront0002.png"
      },
      {
        "file": "banner3fpfront0003.png"
      }
    ] //final direction, so no comma.
  ], // next view is coming, so you need a comma.
  "td": [ //The top down files added the same way as the fist person ones, but with unique file names.
    [
      {
        "file": "banner3tdfront0001.png"
      },
      {
        "file": "banner3tdfront0002.png"
      },
      {
        "file": "banner3tdfront0003.png"
      }
    ]
  ] //closing the final view.
} // End of the sprite. Add a comma here if a second one follows.
] // Closing the file

The json file gets zipped in with the image files, and now the sprite file is ready to be used.

Using a Custom sprite on a map

When using a Custom sprite, first be sure it is installed properly. Do this by placing the zip file with the sprite in the \fxdata folder to use it game wide, in the CONFIGS_LOCATION as specified in the campaign/mappack config file to use it campaign/mappack wide, or name the zip file e.g. map00440.zip and place it with the other files of map 440 to use it on that map only. When the sprite is available for KeeperFX, the next step is to configure an object to use the new sprite instead of the default sprite.

Modifying an Object for a campaign or mappack

Objects in KeeperFX by default use sprites from the .dat file, defined on the AnimationID field for every object in objects.cfg. The default objects.cfg file can be found in the \fxdata folder, but if the campaign or map pack you want to use it on has custom configuration files defined, the settings in the campaign/pack specific objects.cfg will overwrite the default ones.

The objects.cfg file - like all .cfg bundled with KeeperFX can be edited with any text editor, like notepad++.

When for example you want to make the placeholder statue look like a banner, look for the object in object.cfg:

[object132]
Name = STATUE5
Genre = DECORATION
AnimationID = 958

Then update the AnimationID with the name of the Custom Sprite. If this name is not known to you, open the zip file of the custom sprite, open the json file inside with a text editor, and take the value after "name". It should look something like this:

[object132]
Name = STATUE5
Genre = DECORATION
AnimationID = BANNER

When the sprite is rotatable, you could also set the wind direction of the object. Possible values here are: NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST and NORTHWEST. Add this direction with a colon attached to the AnimationID. This would look like this:

[object132]
Name = STATUE5
Genre = DECORATION
AnimationID = BANNER:SOUTHWEST
Changing an object with the Level Script on a single map

Using the SET_OBJECT_CONFIGURATION script command it is possible to change the AnimationID as well. You can make this conditional on map progress. Define the AnimationID as described in the previous chapter.

An example level script:

REM We should have banners facing south
SET_OBJECT_CONFIGURATION(STATUE5, AnimationID, BANNER:SOUTH)
REM If the heroes are defeated, the banner should face north.
IF(PLAYER1,DUNGEON_DESTROYED >= 1)
  SET_OBJECT_CONFIGURATION(STATUE5, AnimationID, BANNER:NORTH)
ENDIF

You can change between different Custom and default sprites, and wind directions as often as you want, provided you remain within the regular script limits.

Bundled custom sprites
name file thumbnail rotatable animated
BANNER
BANNER_NR
banner.zip banner thumbnail 5 sides
No
No
DRUID### druid.zip banner thumbnail 5 sides Yes
FERN
FERN_SMALL
FERN_BROWN
FERN_BROWN_SMALL
fern.zip fern thumbnail No No
GIMLY
GIMLY_NR
gimly.zip gimly thumbnail 5 sides
No
No
GOLDEN_ARMOR
GOLDEN_ARMOR_NR
goldenarmor.zip goldenarmor thumbnail 5 sides
No
No
MUSHROOM_GREEN_LUM
MUSHROOM_RED_LUM
MUSHROOM_YELLOW_LUM
mushrooms.zip mushroom green thumbnail No No
TMAGE### time_mage.zip banner thumbnail 5 sides Yes
TRAP_GEM_RED
TRAP_GEM_GREEN
TRAP_GEM_BLUE
TRAP_GEM_YELLOW
gemtraps.zip gemtrap thumbnail No Yes
TRAP_GREEN
TRAP_PEACH
TRAP_YELLOW
TRAP_WHITE
TRAP_GREENPEACH
trapcolors.zip trapcolor thumbnail
trapcolor thumbnail
No Yes
VINE_TORCH torches.zip vinetorch thumbnail No No
WHITE_FLAG whiteflag.zip whiteflag thumbnail No Yes
WIND_BANNER
WIND_BANNER_NR
windbanner.zip windbanner thumbnail 5 sides
No
Yes