Skin Deep

Skin Deep

50 ratings
Skin Deep Mod Handbook
By BlendoGames and 2 collaborators
The official primer for making your first Skin Deep mod.
2
3
   
Award
Favorite
Favorited
Unfavorite
Introduction
The goal of this guide is to give you up and running in making mods for Skin Deep. To set expectations, this mod handbook is intended as a starting point, just to get you up and running. If you have further mod questions, please ask in the Blendo Games Discord[discord.gg].

This mod handbook was made by Skin Deep's designers: Suzanne Will, Tynan Wales, and Brendon Chung.

You may notice this guide has a lot of overlap with the Quadrilateral Cowboy Mod Handbook. This is intentional: Quadrilateral Cowboy and Skin Deep both use the same technology and share some of the same creators.

Ready? Let's go.

Mod setup
A. Creating the folder
A mod needs a folder to contain all of its files. Let's make a folder:
  1. Enter Skin Deep's root folder.
    By default, this folder is:
    C:\program files (x86)\steam\steamapps\common\skindeep
  2. Create a new folder for your mod. Give it a distinctive name.
    • Keep the folder name less than 16 characters.
    • Do not use spaces in the folder name.
    • Your setup should now look like this:

B. Make a description file
This determines the name of the mod.
  1. Enter your mod's folder.
  2. In this folder, create a file called: description.txt
  3. In this file, enter the title of your mod.
    • This determines what appears in the main menu "Mods" list.
    • The file should consist of just one line.

C. Make a PK4 file
Create a PK4 file. This allows the game to find your mod.
  1. Enter your mod's folder.
  2. In this folder, create an empty file called: pak000.pk4
    • I usually just create an empty text file and then rename it to pak000.pk4
    • Those are three zeroes.
    • Your setup should now look like this:

D. Test it
Let's test your mod!
  1. Run Skin Deep.
  2. In the main menu, select: Mods
  3. Your new mod should appear in the list. Select it and click: Activate Mod

Your new mod is now loaded. Great!

However, the mod doesn't do anything right now. Let's add stuff to it.

Mapping: Tool installation
A. Introduction
To create and edit maps, Skin Deep uses a tool called DarkRadiant. This is the tool we used to make all of the maps for Skin Deep.

DarkRadiant was made for The Dark Mod[www.thedarkmod.com], a great Doom 3 stand-alone mod. The creators of DarkRadiant have graciously made their editor compatible with other games, for which we're tremendously thankful.

B. Tool installation
We'll begin by downloading and installing DarkRadiant.
  1. Download DarkRadiant at: https://www.darkradiant.net/download.html
  2. Install DarkRadiant.
  3. Run DarkRadiant.

C. Tool setup
On initial startup, DarkRadiant will request setup information. Use these settings:
KEY
VALUE
Select Game Type:
Doom 3
Engine Path:
<full filepath of Skin Deep's installation folder>
Mod (fs_game):
<name of the mod folder you created. Note: do not put the full filepath>
Mod Base (fs_game base):
base

Notes:
  • You should be greeted with three main panels: the 3D window, the 2D window, and the Properties window:
  • You can click and drag the boundaries between these panels to resize them.
  • You may want to change the color scheme. In the menu bar, select View > Colours.
    On Skin Deep we used the "Black & Green" color scheme, with some small alterations for readability.

Mapping: Your first room
Let's make a map. Note: This section is pretty long!

Some terminology we'll use here:
ABBREVIATION
DESCRIPTION
LMB
Left Mouse Button
RMB
Right Mouse Button
MMB
Middle Mouse Button

A. What is a brush
Map architecture is made up of solid pieces of geometry, also known as brushes. A brush can be thought of as a building block - if you see a wall, or ceiling, or floor, it's made up of one or more brushes.

B. Make a wall
Let's create a simple wall brush.
  1. In the menu bar, select Grid > Grid256

  2. In the 2D window, press and hold LMB to draw a wall brush. It should look similar to this:
  3. Press ESC to deselect the wall brush.

Done! You just made a wall.

C. Make more walls
One wall is good, but four walls is better. Let's make more walls.
  1. In the 2D window, press and hold LMB to make another wall brush:
  2. Press ESC to deselect the wall brush.
  3. Repeat steps 1 and 2 until you have four wall brushes that look like this:

Four walls! Great stuff. Now let's make the floor and ceiling.

Note: to pan/drag the 2D window:
  1. Move the mouse cursor inside the 2D window.
  2. Press and hold RMB, and move the mouse. This will pan the 2D window.

D. Make the floor
We now have four walls. Let's add a floor brush.
  1. Press CTRL+TAB. This will change the 2D window's perspective. Notice the 2D window is now looking from a side view. It should look similar to this:

    Note: when you press CTRL+TAB, use this widget to verify what view you're currently in:


    Here's what the widgets mean:
  2. Press and hold LMB to draw the floor brush:
  3. Press ESC to deselect the floor brush. Done!

E. Make the ceiling
Let's finish this room with a ceiling brush.
  1. Press and hold LMB to draw the ceiling brush:
  2. Press ESC to deselect the ceiling brush. Done!

We now have four walls, a floor, and a ceiling. Great!

F. Texture the walls and floor and ceiling
We'll now apply textures to this room.
  1. Move the 3D camera inside the room. Move the 3D camera until it appears similar to this:
    Camera Control
    Here's how to control the 3D camera:
    1. Move the mouse cursor into the 3D window.
    2. Press RMB to activate camera mode.
      • Move the mouse to rotate the camera.
      • Press the keyboard's up/down/left/right arrow keys to move the camera.
    3. Press RMB again to exit camera mode.
  2. In the 3D window, move the mouse cursor onto a wall brush.
  3. In the 3D window, press SHIFT+LMB to select a wall brush:
  4. Press S to open the Surface Inspector.
  5. Click the Shader Selection Dialog button:
  6. Select: walls > dev64 and click OK.
  7. Click the X button to close the Surface Inspector:
  8. Press ESC to deselect the brush.
  9. Repeat steps 1-8 until all the walls, floors, and ceilings are textured. When you're done, it should look similar to:

Note: in step 3, you can select multiple brushes. This will allow you to texture multiple brushes at the same time.

G. Place the player start
We now have a textured room. Let's add the player start point.
  1. In the menu bar, select Grid > Grid64
  2. In the 2D window, move the mouse cursor inside the room:

  3. Open the context menu by pressing RMB. (Note: click RMB, do not press and hold it)
  4. Select Create Entity:

  5. Select info_player_start in the list and then click Create:

  6. Press ESC to deselect the entity. Done!

Note: you want the player start to be inside the room. If the placement of the player start does not look right, let's adjust it.
  1. Select the player start point by pressing SHIFT+LMB on the player start point. This can be done in either the 2D window or 3D window (your choice!)
  2. In the 2D window, hold LMB on the player start point. Drag it to where you'd like it. Release LMB when done.
  3. Press CTRL+TAB to look at the player start point from different perspectives. Make sure the player start point is inside the room.

H. Save the map
Let's save your map.
  1. In the menu bar, select File > Save as...
  2. Enter the mod folder you created in the earlier Mod Setup section.
  3. Click the Create Folder button. Name the folder: maps
    The folder structure should look like:
  4. Enter the maps folder.
  5. In the Name field, type: coolmap
  6. Click Save
    Your folder structure should look like:

Note: now that you've saved the map, you can now select File > Save
(you don't need to "Save as..." anymore)

I. Play the map
Let's see your map in the game.
  1. Run Skin Deep.
  2. In the main menu, click the button: Mods
  3. Select your mod from the list.
  4. Click the button: Activate Mod
  5. Open the developer console by pressing: ctrl+alt+tilde
  6. Compile the map by typing in: dmap coolmap

This will run the map. The room is empty and dark, but that's ok!

It should look something like this:


Note: if you run your map and see this error message:
Please refer to the section: APPENDIX: Map leaks


Mapping: Things to try, vol. 1
You made a room! Nice.

Here's some other things to try out in the map editor.

A. Resize a brush
How to resize a brush:
  1. Select a brush by pressing SHIFT+LMB on it. This can be either in the 2D window or 3D window (your choice!)
  2. In the 2D window, position your mouse cursor to the side of the selected brush. Any side of it is fine.
  3. Press and hold LMB and move the mouse. Notice this will resize the brush:

B. Move a brush
How to move a brush:
  1. Select a brush by pressing SHIFT+LMB on it. This can be either in the 2D window or 3D window (your choice!)
  2. In the 2D window, position your mouse cursor on the selected brush.
  3. Press and hold LMB and move the mouse. Notice this will move the brush:

C. Duplicate a brush
How to duplicate a brush:
  1. Select a brush by pressing SHIFT+LMB on it. This can be either in the 2D window or 3D window (your choice!)
  2. Press spacebar. Notice this will duplicate the selected brush:
Note: duplication is useful for building out spaces. For example:
  • instead of manually creating all walls of a room, build just one wall and then duplicate & resize the rest of them.
  • if a room has a series of repeating elements, such as columns or staircases, the duplication tool can be helpful.
  • The spacebar duplication also applies to entities. Example: if you select a pirate and press spacebar, you'll duplicate the pirate.

D. Delete a brush
How to delete a brush:
  1. Select a brush by pressing SHIFT+LMB on it. This can be either in the 2D window or 3D window (your choice!)
  2. Press backspace. Notice this will delete the selected brush:

E. Add a light
You may have noticed your room is very dark. This is because there's no light source in it. Let's do something about that.
  1. Right-click inside your room.
  2. In the context menu that appears, select Create Light...

  3. Done! Similar to brushes, lights can be moved and resized. Try running your map in Skin Deep and check out your new light.

Note: while you're here, try adding other entities.

Refer back to the earlier section G. Place the player start and try placing other entities from the entity list. Try placing a:
  • moveable_item_shotgun
  • moveable_soda
  • monster_engineer

F. Change texture scale, offset, and rotation
You can adjust how a texture looks on a brush. Here's how:
  1. Select a single surface on a brush in the 3D viewport with CTRL+SHIFT+LMB. Notice how this is different from selecting the whole brush.
  2. Press S to bring up the Surface Inspector.
  3. Have a look at the various fields and buttons you have available to you. Experiment with them and see how they change the texture mapping on the surface.
Notes:
  • If you ever find that your texture mapping has gone awry, you can click the Natural button to restore it to a sane state
  • Many textures in Skin Deep are designed to be used at a scale of less than 1 (e.g. 0.5 or 0.25). Try studying the game's levels to see what texture scales we use.
  • For a different approach to texture mapping, try opening the Texture Tool with CTRL+ALT+T. This is a little more akin to a 'modern' UV mapping interface, and lets you drag the surface vertices around in order to fit them onto a part of the texture.

There's a lot more to explore and learn, and hopefully this gives you a starting point.
Mapping: Things to try, vol. 2
A. Add a patch
A patch is a special smooth surface. Patches are extremely useful for curved surfaces, organic shapes, pipes, pipes, pipes, and more pipes. To start, let's create a simple rectangular patch:
  1. Click and drag within the 2D viewport to create a rectangular brush.
  2. Select from the menu bar: Patch > Create Simple Patch (you can also press SHIFT+P):

  3. Click 'OK' on the pop-up dialog:

    The 'width' and 'height' numbers here are not the size of the object. These values set the amount of control points on the patch. Let's use these default values for now.
  4. Your brush has now been turned into a basic patch. Fly around in the 3D viewport and notice that it's now a paper-thin surface that's only visible from one side:

  5. Press the 'Select Vertices' button on the top toolbar (or press V) to enter vertex edit mode:

  6. Notice that the patch now has a number of green and pink vertices highlighted across its surface. Select some vertices with SHIFT+LMB. Drag them around. You can also press W to toggle a translation widget, as pictured here:


  7. Notice how the patch deforms between the control points. Experiment with them and get a feel for how the green and pink control points differ.
  8. When done, press the 'Select Vertices' button on the top toolbar (or press V) to exit vertex edit mode:
Notes:
  • Patches can be textured like brushes. Try assigning a texture to your patch.
  • You can create different types of patch from the Patch menu. Create a brush and then select from the menu bar Patch > Create Cylinder or Patch > Create Cone.
  • Brushes will 'seal' leaks from the void, but patches do not. Be careful when using patches to create walls or floors, or you may create a leak (see Appendix: Map leaks).
  • The smoothness of a patch's curve can be overridden by selecting the patch and pressing SHIFT+S. In this dialog box, you can change the Patch Tesselation, which adjusts how smooth the patch is.

B. Clip a brush
You can 'clip' a brush to chop it up. This is a safe and stable way to create shapes that aren't rectangles.
  1. Select a brush by pressing SHIFT+LMB on it.
  2. Click the Clip Tool button on the left toolbar (you can also press X) to activate the Clip Tool:
  3. In the 2D window, click once to define the first point. Then click once at a different location to define the second point. This will create a clipping plane, which will split the brush down the highlighted line:

    Note: press and hold LMB to drag the 2 points (the blue dots). This allows you to adjust the clip angle.
  4. Press SHIFT+ENTER to cut the brush into two separate brushes, which can be independently selected, moved, and deleted.

    Notes:
    • You can select multiple brushes and clip them all at once.
    • You can just press ENTER instead of SHIFT+ENTER to immediately discard the brush on one side of the clipping plane. CTRL+ENTER toggles which side gets discarded.
    • Try to ensure that the clipping plane points are exactly on the edge of the brush that you're clipping. This will make sure that all the vertices on the new chopped brushes are neatly aligned to the grid, and make them easier to work with.
    • When you clip a brush, the editor will automatically fill the interior faces with a special material called caulk. You can think of caulk as a 'null' material: it's invisible and doesn't appear in the game.
  5. Click the Clip Tool button on the left toolbar (you can also press X) to deactivate the Clip Tool:

Steam Workshop: Publishing
Feel like sharing? Upload and share your mod on the Steam Workshop.


A. Skin Deep Workshop Uploader installation
To share mods, first install the Skin Deep Workshop Uploader.
  1. In your Steam window, click LIBRARY.
  2. Click TOOLS.
  3. In the list, find Skin Deep Workshop Uploader. Double-click it to install.
    If you're having trouble finding it, try using the Steam search bar. Type in: skin

    and it should filter the results to show the Skin Deep Workshop Uploader.
  4. Done!
Skin Deep Workshop Uploader will now appear in your Steam library (in the TOOLS section).

B. Uploading your mod
Now that the uploader tool is installed, let's upload your mod to the Skin Deep Steam Workshop.
  1. From your Steam library, run Skin Deep Workshop Uploader.
  2. Click the Add new mod button.
    • Fill out all the fields.
    • For the Thumbnail field, point it to an image file. This image will be the preview image for your workshop item.
      • The image should be 16:9 aspect ratio. Example image resolutions: 1920x1080, 1280x720.
      • The image should be PNG or JPG.
    • For the Data folder field, point it to the folder that contains your mod.
      This is the folder you created in the earlier Mod Setup section.
  3. Click the Add mod to Workshop button to start the upload. Done! Your mod is now available on the Skin Deep Steam Workshop.

C. Updating your mod
If you'd like to update your mod with new changes/additions/etc:
  1. Run Skin Deep Workshop Uploader.
  2. Your published mods will appear in the list. Select the mod you wish to update.
  3. Click the Update mod button.
    • If you wish to change any mod files, fill in the Mod folder field. Or, leave the field empty if you don't want to change it.
    • Optionally, fill in the Update note if you want to include notes for the update.
  4. Click the Upload changes button to commit the changes. Done!

APPENDIX: Map leaks
When you run your map, you may see this error:
Leaks must be fixed before the map can be run.

A. What is a "leak"?
A "leak" is when a map is not completely sealed-off from the void. Let's explain it with an example:

Here's a simple one-room level:


Let's consider everywhere outside the playable space to be the void:


A "leak" is when the void "leaks" into the playable space. For example:


Yup, there's the leak:


Basically, the level has to be constructed to be 100% completely airtight from the void.

B. How do I fix a leak?
Leaks are sometimes very easy to find, and sometimes very difficult to find. As a level gets larger and more complex, leaks can sometimes be akin to finding a needle in a haystack.

One way to find a leak is to use DarkRadiant's "Pointfile" feature:
  1. After Skin Deep warns you about the leak, return to the DarkRadiant map editor.
  2. In DarkRadiant, select File > Pointfile
  3. A red line will be drawn in both the 2D window and 3D window. Follow the red line:

Note: sometimes the Pointfile may seemingly point nowhere.

It's trying its best, but sometimes it is not helpful.

Note: if you're having trouble finding a leak, it may be because you've accidentally placed an entity in the void. An entity is basically anything that's not a brush. For example: a light, a player start, a door, a prop, a gun, a pirate, etc.

APPENDIX: Ship Pre-Production
Creating a ship from scratch can be daunting. To make it more manageable, here's a version of the process we used to make ships on Skin Deep.

A. Design document
While it's tempting to jump straight into the level editor, sometimes it helps to get some fundamental guiding principles straightened out first. Open a document and try to answer a few questions for yourself:

  • What is the ship's core theme or function in-fiction? Is it a mobile bank? A greenhouse? A car wash? A battleship? Think about what gameplay features might arise from this. On Skin Deep, we endeavoured to have every ship include unique features that reflected its in-fiction purpose.
  • What might it look like from the outside?
  • What rooms might it have?
  • For each room, ask:
    • What is the in-fiction purpose of this area? What do people actually do here in the setting? How do they get around it?
    • What is the flavour of the gameplay in this area? Is it tight and claustrophobic? Is it a playground? How big or small should the room be?
    • What are the main elements in this space? Is there machinery? Is there something parked or stored here?
    • What is the main colour palette of the surfaces within the room? Try to make this differ from adjacent rooms.
    • What is the lighting like? What mood does it give off? What are the colours and intensities?

Try to remember that this document is only a starting point. This document is not intended to be rigidly followed, and it is okay and very expected to iterate and change things during level construction. The design process is rarely so linear that everything follows perfectly neatly.



B. Blockout
Once you have some ideas cooking, it's a good idea to start building a blockout in the level editor.

If you're not familiar, a blockout is essentially a level design 'sketch'. The goal is to create something that's functional, but has absolute minimal visuals and polish.
  • Use dev textures (e.g. textures/walls/dev64).
  • Keep lighting as basic as possible.
  • Keep geometry very blocky and rudimentary.

Blockout of sh_radio01.map ('Narwhal')

When blocking out each room, consider:
  • How is the in-fiction purpose of the area represented? Are there any elements that need space set aside for them? It's okay if they're just featureless cubes at this point, but you need to know what they represent.
  • What are the player's routes? How does the player traverse this space? Do they have ways to get around without being seen? Maybe you want to deliberately make it hard to get around—that's okay too!
  • What are the pirates' routes? How do enemies traverse this space? Do they have enough room to manoeuvre?

As well as the rough geometry, you will also need to place interactive elements to make the level playable: pirates, patrol routes, doors, windows, trash chutes, vents, cameras, turrets, info stations, all that good stuff.

It's okay if bespoke functionality isn't in the level at this stage—if your ship is a recycling centre, you don't need a full bottle recycling minigame implemented. The important thing is making it playable.

Blockout of sh_vault01.map ('Chiton')


C. Test and iterate
Once you have a playable level that you can run around in, it's time to test and iterate.

Broadly speaking, this means jumping into the level, playing it, and seeing if it feels good. Try to get feedback from other players, if you can. If something feels wrong, don't be afraid to tear it apart and replace it with something new; the point of a blockout is to make it easy to modify or throw things away if they're not working. You might also have new ideas which conflict with things you defined in your design document—that's okay too!

Keep testing and iterating until you're happy with the functional side of the level. Once you are, it's time to move on to detailing and sprucing everything up. Be aware that it becomes a lot more inconvenient to change your level once the detailing starts, so try to nail things down here if you can.

APPENDIX: Production Checklist, vol. 1
Skin Deep is a complex game with a lot of moving parts. For this reason, it can be difficult to remember all the things that need to go into a level before it can be considered 'finished', even if you have added all the necessary entities.

The production checklist was created to help us catch some common mistakes that arose during level construction:
  • Playerclip and monsterclip are placed on all complex geometry and static models, for player traversal reasons and enemy pathfinding reasons. Remember that zero-G is always a possibility and certain monsters (e.g. swordfish) can fly, so monsterclip needs to apply to ceilings as well!
  • Ledges without railings should have a margin of nowalk brushes around them. This is a special material that keeps the pirate AI from walking too close to the edge of the ledge.
    This is how nowalk is used. Note the blue brushes wrapping around the ledge here.

  • Pirates have patrol paths, with evenly-spaced nodes that don't stray too close to organic hiding spots.
  • Sound ambience is present in the level. Give each room a 'base' ambience, and consider adding other ambient sounds for machinery, unique features, etc.
  • Ambient particle effects are present. Consider sparks from machinery, dust and fog from fans and vent grates, etc.
  • Each space should have an info_location with a player-facing name (use the 'location' keyvalue to name it—it will appear on the infowatch and in some other places). Use the console command g_showUnassignedLocations to see if areas don't have assigned locations.
  • Exits to named rooms should be labelled with signage.
  • Rooms should have a large decal label somewhere within them (preferably somewhere highly visible) with their room name on them. This helps players identify rooms more easily.
  • Verify that inter-room vent doors (vents that connect one room to a different room) have room labels correctly set up on them.
  • Vent interiors use trigger_confinedtunnel to mark them as 'vent' spaces, and control the player's ability to turn around.
  • Informal crawlspace hiding spaces use trigger_hide to help conceal the player.
  • Vents have adequate env_ventpeeks to allow the player to peek into adjoining rooms and orient themselves.
  • Vent spaces have a valid location, ambience, and reverb setting. A room's reverb setting is set in the info_location for the room.
  • For ventdoors in the floor and ceiling, ensure the ventdoor aligns the player correctly when entered (use the targetyaw keyvalue). This automatically turns the player's angle toward a default direction when they enter the vent, making it easier to traverse.
  • No internal leaks (i.e. leaks between adjoining rooms) exist.
    This one can be notoriously difficult to diagnose and fix. Here are some techniques to help:
    • Examine the console upon loading a level. If two locations 'overlap' (say, because there's a leak between them), the console will print a warning.
    • Use r_showPortals 1 and compare the portals in the level to the portals you placed in the editor. If a portal is missing in-game, that usually indicates the compiler was able to find a way around it, and consequently eliminated it.
    • Use r_showtris 3 and see if the game is drawing geometry outside of the room you're currently in. If you can see another room's triangles, that usually indicates that there's a leak to that room.
  • Patches have an appropriate level of tessellation for their size. Beware of accidentally creating a super-small, super high-density patch—this might be expensive to render.
  • All visible light sources are breakable, and breaking the visible light source causes its light volumes to turn off.
  • If all the lights in a room are destroyed, the approximate room outline should still be readable (this is primarily achieved with glowing 'trim', like the trim_lightglow textures).
  • Exterior windows should have a visportal, a windowclip surface, a func_windowseal, a func_windowshutter, and an info_vacuumseparator. Make sure they're all targeting each other correctly.
  • If an exterior window isn't aligned to the cardinal directions, you will also need to manually place the env_lever_windowseal.
  • Insides of doorframes are textured.
  • Doors and vents do not visibly clip through anything when opened.
  • Stairs have the 'cat ramps' on them (this is far from a strict requirement, but remember it's an option!):
  • Verify that the amount of lighting overlap is acceptable.
    Note: use r_showlightcount 1 to verify that lighting overlap is within a performance-friendly range.
    • Green-yellow range (1-3 lights) is ideal, but not necessarily attainable
    • Try to avoid having white (7+ lights).
    • It's usually okay to have higher overlap if it overlaps on a very simple surface (e.g. a flat floor), but less okay if it's overlapping on complex geometry.
    Usage of r_showlightcount 1
  • Verify that performance of the room is acceptable with all doors to adjacent rooms open. Use g_dragentity 1 to force doors open if necessary.
  • Splits acropoints (i.e. info_acropoint_splits) align the player correctly if necessary. Use the keyvalue pair autodir : 0 to force alignment to the entity's forward direction.

APPENDIX: Production Checklist, vol. 2
  • Info Stations: Place one in each room. Info stations are used to call in repairs to the room they are in, so any room without one might not be able to be repaired.
  • Repair bot Hatches: Place one in each room. This is how a repair bot will get to the damaged entities. There are several sizes to support smaller room scales.


  • Lost and Found Machine: Place only one in the level. Typically these were placed in the same room the player spawned in to ensure they weren't locked behind a door or otherwise made inaccessible.
  • Signal Lamp Kits: We tried to place these near every airlock and window on the interior. For the exterior, we also placed them next to trash chutes. These are essential for the player to be able to call in a rescue pod for the cats.
    Note: if the player destroys all (or almost all) signal lamps in the level, there's an automatic failsafe that spawns a signal lamp in the lost and found machine.
  • Health Stations: While not technically required, it sure is nice to give the player a way to heal. We usually placed 2-3 of these based on the size of the level.
  • Wall speakers: These objects are where ship announcements and countdowns come from. Quite important for player comprehension of ship events. One in each room and each hallway - doors can occlude sound quite strongly so one should be near the player with all doors shut.


  • Pirate Respawn points: These need to be in each room. Based on the shape and size of the room you may want a few. They should be in hallways too.
  • Cat Cages: Very important! The player wants to rescue these adorable animals. These were typically placed based on ship size and difficulty.
  • Pathfinding Entities: These are necessary for the map to properly generate pathfinding for AI entities. ass_flood24 is for pirates and aas32_flood_flybot is for repairbots and spearbots.
  • FTL: Earlier in development these drives had a greater impact on gameplay. They are still required in a map but can be placed in a room or on the exterior. There are several sizes to try.


  • Turrets: Everybody loves turrets. Place them where they will have a good firing arc but also allow players cover and routes to approach them.
  • Security Cameras: These are completely optional and add another layer of challenge for the player. Make sure you place a Camera Splice in a nearby vent so the player can take over the connected Security Camera.
  • Cryo Spawner: The player spawns in a little closet out in space and then is teleported to the env_cryospawn that is in the level. Outside of your skybox make a tiny room that contains only an env_cryointerior.
  • Skybox Color: Make your large exterior sunlight match the color of your skybox. If you want to use the same setup as the shipping maps from Skin Deep, copy the little box floating out in space that contains a miniature skybox. Inside it there is a func_static of the wormhole tunnel. This entity can accept the _color property to change the color of your skybox texture.


  • Airlock Accumulators: Each airlock should have 2 accumulators. Damaging or using these will rapidly decompress the airlock and cause the room to go zero g for a few seconds.


    How to setup accumulators:
    1. Place an env_airlock_accumulator entity where you want it.
    2. Build a hose using flat patch brushes with the cable_air_01 material on them. The patches should connect the accumulator to the guage in the upper-left corner of the airlock door.
    3. Make the patches into a single func_static.
    4. On the env_airlock_accumulator entity, target the airlock first. (select the accumulator, then the airlock entity, and press ctrl+K)
    5. Target the accumulator to the func_static you built for the hose.
    6. Do these steps one more time for the second accumulator.

    These steps will help your map follow the same guidelines the Skin Deep level designers did.






APPENDIX: Ship Exterior Checklist
Ship exteriors need to be both visually legible and easy to traverse. We have various techniques to ensure both, but it can be difficult to ensure all of them are covered. This checklist should help confirm what the needs & wants of the ship exterior.

  • Red triangle decals (i.e. textures/exterior/decals/triangle02_red_lit) should be positioned near all points of entry, pointing towards them. Ideally, these decals are placed in such a way that they are visible from many angles.
  • Garbage chute exits should have a trash fish hive nearby.
  • If a point of entry is not naturally reached by sunlight (e.g. because it is on the far side of the ship, or the underbelly), then it should be illuminated by an exterior light source to draw attention to it. (e.g. perhaps a light fixture of some kind)
  • Paint patch decals (e.g. textures/decals/pipedetail_paintpatch) should be wrapped around edges to help players make sense of the topology of the ship (and to make the ship look cool and grungy). The original purpose of these splotches was help make silhouettes and shapes more readable, to help player traversal and navigation.
  • The rear of the ship should have engine boosters.
    Engine boosters contain the following:
    • The decal textures/exterior/decals/booster01 on the back of the ship.
    • A particle emitter producing some variant of amb_booster01.prt (we have a number of these, for various sizes/shapes of booster).
    • A 'spritetube' model (e.g. models/objects/spritetube/booster192.ase).
    • A light volume, to illuminate things that pass nearby the booster
    • A trigger_enginewash volume trailing behind the booster (this is the part that hurts you if you float into it).
  • Grab rings should be distributed around the hull to facilitate traversal.
  • Zip lines should run along the hull for similar reasons (try to consider your zip line placement—should they help the player get from one entry point to another?)
  • All airlocks should have track lights pointing to them from above and below (preferably wrapping around the hull, if applicable, so they can be seen from oblique angles).
    Airlock track lights
  • Diagnostic boxes (env_diagnosticbox) should be placed prominently on the top/underside of the ship to aid in navigation.
  • Outer space should have an info_location with the the keyvalue “location” : ”#str_00000”. This is how some of our code identifies where outer space is, so it's very important!
  • The distance between the ship's hull and the skybox should be about 384 to 512 units.
  • 'Navlights' should be distributed across the ship's surface (Green for starboard, red for port, orange for everything in between). A navlight consists of both a decal and a small light volume that is synced to its sequence.
  • Airlocks facing away from the sun should have a shadow_sunlight brush across the inner airlock doors (this prevents odd lighting artifacts while the exterior airlock doors are open)
  • Signal lamp kits should be placed around all airlock exteriors and windows (make sure they use the skin skins/objects/signal_kit/skin_exterior to get correct lighting on them).
  • 'Whisker' antennas should be placed around the Bridge windows



The above production checklists are what helped us create the ships in Skin Deep.

We found these checklists helpful, but please don't feel beholden to these guidelines. If you have an idea you want to try, go for it. Explore and experiment -- that's the lovely part of modding.
APPENDIX: Making a map image
Each ship has a 2D map image that is used for both the Info Stations throughout the ship as well as the wrist watch map that Nina uses.

This should be done later in level design process, to reduce the amount of changes/updates to the overhead map image.

A. In the Editor
Let's start in the map itself. Open the editor and let's add a few things.
  1. Look at your map from the TOP view. This is how the player will view your map.
  2. Place 2 target_null entities to mark the bounds of the overhead map.
    • Place 1 on the TOP LEFT of the level. Name the entity: loc_topleft
    • Place 1 on the BOTTOM RIGHT of the level. Name the entity: loc_bottomright
    Notes:
    • The two placed entities need to create an exact square. (Tip: select both target_null entities and the editor will draw the dimensions of your selection.)
    • The two entities should encompass a snug fit of the level interiors. Allow a ~32 unit buffer margin around the interiors.
    • The Z (height) doesn't matter. Only the X and Y coordinates will be read.

  3. Click on any brush that is considered worldspawn (any non-entity brush).
  4. Add these values to the entity:
PROPERTY
VALUE
map_topleft
loc_topleft
map_bottomright
loc_bottomright
mtr_image
guis/map_<YOURMAPNAME>

B. Image Creation: Reference image
  1. Open this file: base/materials/mapgui.mtr
  2. Add a material entry for your map. (Use guis/map_remora as a template)
  3. We'll now make a reference image that we'll draw over.
    • Go into the Editor.
    • Go to the overhead ortho view (Top).
    • Take a screenshot of the entire level, ensuring that your two target_nulls are included.
    • Now in an image editor, crop the screenshot so it is a perfect square. Use your two target nulls as the upper left and lower right corners.

  4. Resize this image to be 1024x1024 pixels.
  5. You're done with the reference image, now onto drawing the map itself.

C. Image Creation: Drawn Map
  1. We want broad, big details. We want to avoid small, minute details.
  2. The image doesn't have to be 1:1 accurate. The room bounds need to be accurate enough to encompass the location of all entities.
  3. Err on making the rooms a little too large instead of too small.
  4. Now draw on a new layer on top of your reference image. Big, bold shapes instead of tiny details.
    Metrics for Skin Deep
    These do not need to be followed unless your goal is to make maps that look like the ones in Skin Deep.
    • Walls are drawn with lines that are 7 px
    • Vents are shown with dotted lines. Each round dot is 14 px.
    • Room alpha fill color is #404040 (White at 25% opacity)
    • Hallway alpha fill color is #202020 (White at 13% opacity)
    • Draw in windows as little boxes.
    • Add doors as 14 px rectangles.
    • Use the icon for airlocks to show all airlock locations. (An example is in map_remora.psd)
  5. Hide the layer that had your reference image in it.
  6. Make sure your background is set to transparent. The image should be a set of mostly-transparent rooms with opaque white lines and icons.
  7. Save the image as a TGA.
  8. Once you have saved the image, make sure to go back into the editor and fill in your image file name in the Worldspawn.

D. Adding Room Names
You'll need to add your room names to your maps. This is done on the data side in a file called base/def/maps.def.
  1. First, you need to find the positions of where you want your room names to draw.
  2. These X and Y positions are normalized values ranging between 0.0 - 1.0.
    Tip:
    Here's a good way to find room name positions.
    • Open your map image.
    • Temporarily resize the image to 1000 x 1000 px.
    • Move the mouse cursor to where you want a location to be.
    • Get the coordinates and then reduce them by dividing by 1000.
      • For example: 234 x 727 would result in coordinates of .23 x .72.
  3. Now open the file mentioned earlier, base/def/maps.def.
  4. Copy the formatting you see for other maps, or follow the table below:
"roomlabel0"
"YOUR_ROOM_NAME"
"roomlabel0_x"
".23"
"roomlabel0_y"
".72
"roomlabel1"
"YOUR_OTHER_ROOM_NAME"
"roomlabel1_x"
".47"
"roomlabel1_y"
".22

Everything should now be ready to run in the game. Give it a test by loading your level and looking at the wrist watch and double checking the info station.







APPENDIX: Console commands
The developer console has helpful debug commands available for use.

A. Opening the console
Press ctrl+alt+tilde to open the console.

Note: this can be streamlined.
  1. In your Steam library, right-click on Skin Deep
  2. Select Properties > General > Launch Options
  3. Paste in: +set com_allowconsole 1
Now when you run the game, you can now just tap tilde (instead of ctrl+alt+tilde) to open the console.

Note: if your computer keyboard layout doesn't support the tilde key, you can alternatively press Shift+Escape to open the console.

B. Helpers
Because it's not reasonable to memorize all commands, there are ways to find/search/recall commands.
  • "find" - "find" is great for searching for commands. For example, to list all console commands that have the word "damage" in them, type in: find damage
    ✨We highly recommend using "find" as it's very useful for discovering and exploring console commands.
  • tab autocomplete - Pressing tab will do autocomplete. For example, type in "g_" and then press tab.
  • command history - Press up arrow and down arrow to scroll through previous commands you've used.
  • command help - Typing in the command by itself will sometimes give help text. For example, type in: g_ruler
  • hotkey bind - It's extremely helpful to bind often-used commands to your keyboard.
    Example:
    bind p noclip
    will make the 'p' key make you fly.
  • toggle bind - "toggle" will alternate 0/1 for a given variable. This is great for hotkey binds.
    Example:
    bind h "toggle g_ruler"
    will make the 'h' key make the ruler turn on/off. Note the command is encapsulated inside quotation marks.

C. Helpful console commands
COMMAND
DESCRIPTION
god
Toggles invincibility.
noclip
Allows you to fly and pass through walls.
notarget
Makes enemies not see you.
spawn [entity]
Spawns an object in the world.

For most cases, we recommend:
  1. Type in: spawn moveable
  2. Press tab for autocomplete. Notice it will list all moveable objects. Press PGUP to scroll up the list.
damageEntity
Apply massive damage to whatever you're looking at.
killmonsters
Deletes all monsters in the level.
g_stoptime [0/1]
Freezes time. The player can still move around.
g_ruler [0/1/2]
Draws a measurement ruler.
g_showmaterial [0/1]
Displays name of material you're looking at.
g_showmodel [0/1/2]
Displays name of model you're looking at.
r_showtris [0/1/2/3]
Draws wireframe display.
r_locksurfaces [0/1]
Pauses updating of level culling/visibility. This is helpful for determining what the engine is and isn't rendering from a given location.
g_entityEditMode [0/1]
Light editor. This allows you to edit lights in the game engine. Move them, resize them, change color, and more. You also have the option to save your changes to the .map file.
r_showlightcount [0/1]
Displays amount of light overlap. The idTech4 game engine is sensitive to how many lights are overlapping, so less overlap is generally better for performance. The color display ranges from green (good) to super-nasty (white):
  • Green = 1 light 👍
  • Yellow-green = 2 lights
  • Yellow = 3 lights
  • Orange = 4 lights
  • Red = 5 lights
  • Pink = 6 lights
  • White = 7+ lights 💀
debugSetCombatState [0/1]
Manually set the global combat state.
debugFuseboxUnlockAll
Unlocks all fuseboxes in the map
g_dragEntity [0/1]
Hold LMB to physics-drag things around. This also works on locked doors.
aas_showareas [0/1]
Show pathfinding cells on the ground. This command is helpful for verifying that the pathfinding data looks correct.
ai_showstate [0/1]
Displays AI's current state above their head.
con_noprint [0/1]
Displays a few lines of console text in the main game window. If you're doing mod development, we highly recommend setting this to '0' so that you can see debug output while playing the game.
r_showportals [0/1]
This displays whether a portal is open/closed. This is helpful for verifying your portal setup is working as intended.
locateEntityViaName [name]
This will find and draw an arrow at all entities with a given name. Note: this does a substring search, so any small fragment of the name will work here.
locateEntityViaDef [name]
Finds all entities via their definition name. For example, if you want to find all instances of health stations, type in:
locateentityviadef env_healthstation
g_showEntityInfo [0/1/2]
Displays information for all entities in the world.
g_showCollisionModels [0/1]
Displays entity collision information.
g_showHud [0/1]
Hides the HUD display.
debugNotesReadAll
Reads every note and puts them in the memory palace.
debugNotesLocate
Draws an arrow toward every note.
debugNotesReadAll
Reads every note and puts them in the memory palace.
debugNotesNext
Teleport to next note.
debugNotesPrev
Teleports to previous note.


APPENDIX: Hot reload
Generally, you never need to exit the game to see your changes. In most cases, you don't even need to restart the map.

idTech4 has what is sometimes called "hot reload", where you can instantly see your changes. This is a huge time saver, and was essential in allowing us to move quickly and iterate on the game.

A. Reload commands
COMMAND
DESCRIPTION
reloadAnims
Reloads .md5anim animation files.
reloadDecls
Reloads .def entity information files and .prt particle files.
reloadGuis
Reloads all .gui files.
reloadImages
Reloads image files, i.e. for walls, characters, ui, etc.
reloadLanguage
Reloads the .lang language localization files.
reloadMap
Reloads the .map file. Make edits in DarkRadiant and instantly see the changes in the game. This is useful for adjusting lights, moving entities, deleting entities, and adding entities.

Note: this is functionality from The Dark Mod[www.thedarkmod.com]. Thank you!
reloadModels
Reloads .ase and .md5mesh model files.
reloadSounds
Reloads .wav and .ogg sound files.
reloadDecls
Reloads entity definition information.
reloadScript
Reloads .script files. Note: this will restart the map.

B. Hot reload hotkey
Instead of manually calling reload commands, we recommend making a hotkey that reloads (almost) everything.

  1. Open the console (ctrl+alt+tilde)
  2. Paste in:
bind enter "reloadDecls;reloadGuis;reloadImages;reloadModels;reloadSounds;reloadanims"
This will will make pressing Enter hot-reload most game assets, i.e. sounds, textures, etc.

C. Special note for entity information
'ReloadDecls' in some contexts is a special case. If you edit a .def file to change an entity's properties, you may notice that 'reloadDecls' seemingly doesn't instantly hot reload the changes.

Example: increasing a teapot's health from 3 to 30.

The reason for this is because:
  • The value changes are being loaded, yes.
  • However, the changes only apply to entities spawned after reloadDecls was called.

The workaround for this is:
  • Restart the map with: map [mapname]
  • Or, spawn a fresh instance of the entity. For example: spawn moveable_teapot



APPENDIX: Explore the game files
A large amount of the game data in Skin Deep is contained in text files. This means: you can open them up and take a look exactly at how Skin Deep's maps, scripts, and gameplay info are all set up.

✨Exploring our game files is a really great way to learn how we made everything in the game. Nothing is locked up or hidden. It's all available for you to examine.✨

Here's a primer to get you started:

Open the Skin Deep maps
  1. Load the map editor DarkRadiant.
  2. In the menu bar, select File > Open...
  3. Go to the folder that Skin Deep is installed in.
    By default, this folder is:
    C:\program files (x86)\steam\steamapps\common\skindeep
  4. Go into the base folder.
  5. Go into the maps folder.
  6. These are all the map files that shipped with Skin Deep. Open them up and take a look!

FILE
DESCRIPTION
vig_tutorial01.map
CSS Wobbegong | Junker Barge
vig_hub.map
Nina's Habitat | Hub Level
sh_laundromat01.map
Periwinkle | Laundromat Barge
sh_lighthouse01.map
Angler | Lighthouse Station
vig_surveil.map
Asteroid 92 | The Stakeout
sh_observatory01.map
Stargazer | Observatory Vessel
sh_library01.map
Herring | Library Freighter
vig_penthouse.map
Celestial Penthouse | Little Lion Returns
sh_restaurant01.map
Remora | Restaurant Ferry
sh_radio01.map
Narhwal | Radio Station
sh_windfarm01.map
Barreleye | Wind Farm Tanker
sh_postoffice01.map
Fugu | Post Office Barge
vig_convention.map
Dentist Convention | Planting The Bug
sh_vault01.map
Chiton | Secured Vault Freighter
sh_mining01.map
Portunid | Mining Tanker
sh_mechrepair01.map
Beluga | Mech Repair Frigate
sh_cargo01.map
Minnow | Icebreaker Vessel
sh_cargo02.map
Guppy | Algae Refinery Tanker
vig_miaocorp.map
MIAO Corporation | Performance Review
vig_lionship.map
Wonky Space | Assault on Good Twin Castle
vig_memories.map
Good Twin Castle | The Zena Zone
vig_beachparty.map
The Beach | Beach Episode
vig_credits.map
Credits Chamber | The Implementors

Note: if you make changes and accidentally save over any Skin Deep files, you can revert it back to its original version.

In your Steam library, right-click on Skin Deep and select:
Properties > Installed Files > Verify integrity of game files


APPENDIX: File types
FILE EXTENSION
DESCRIPTION
OPEN WITH
.map
Map file.
DarkRadiant
.prt
Particle effects. This is where particle effect data is stored.
DarkRadiant
.def
Definition file. This is where data is set. i.e. health, ammo, damage types, etc.
text editor
.sndshd
Sound shader file. This is where audio assets are defined.
text editor
.efx
Environmetal audio file. This allows you to set audio environmental effects for a room. i.e. reverb, etc.
text editor
.gui
GUI file. This is where the in-game screens are set. i.e. the info stations, the health stations, main menu, etc.
text editor
.script
Script file. This is where map and entity scripting is set.
text editor
.skin
Skin file. This allows a model to swap to a different set of textures.
text editor
.fx
FX file. This allows you to choreograph effects involving particle effects, sounds, and lights.
text editor
.mtr
Material shader file. This is where materials are defined. i.e. what texture to use, whether it animates, how shiny it is, etc.
text editor
.glsl .frag .vert
Shader files. These allow you to write more complex visual effects.
text editor
.cfg
Configuration file. This allows you to run a series of console commands, usually for development purposes.
text editor
.lang
Localization file. This is where localized strings are stored. We wrote an internal tool for this: https://blendogames.com/news/post/2025-03-24-localizer
text editor
.pda
Email file. This is where the in-game emails are stored.
text editor
.dict
Gamepad glyph file. This maps button images to different gamepad controller types.
text editor
.tga
TGA image file. This is the image format we used for Skin Deep. Can be saved in 16-bit (no alpha channel) or 32-bit (has alpha channel).
Image editor. i.e. Krita, Photoshop
.wav
Audio file. This is the audio file format we used for Skin Deep. Sound effect files must be:
  • 16-bit
  • Mono
  • 11025khz, 22050khz, or 44100khz
We wrote an internal tool to browse audio assets: https://blendogames.com/news/post/2025-03-03-wavtool
Audio editor. i.e. Audacity
.ase
Non-animated model. This is for props that do not have moving parts. i.e. a table.
Model editor. i.e. Blender
.md5mesh .md5anim
Animated model. i.e. pirate, cat, etc.
Model editor. i.e. Blender
.proc .cm
Geometry and collision information for maps.
(generated during DMAP process)
.aas*
Map pathing file. This stores information for NPC pathfinding.
(generated during DMAP process)
.roq
ROQ video file.
(generated via FFMPEG[ffmpeg.org])
.af
Articulated figure file. This sets information for ragdoll joints and ragdoll collision.
(edited through EditAFs command in retail Doom 3)

APPENDIX: Further reading
Additional resources and further reading:

Mod Museum
A guided behind-the-scenes tour of how things work in Skin Deep.
Map Kit
Sample maps that demonstrate various features of Skin Deep.
id Dev Net
id Software's official documentation for idTech4.
The Dark Wiki
Documentation for The Dark Mod, with many tutorials.
Note: some concepts here are specific to The Dark Mod and are not applicable to Skin Deep.
Mod Wiki
Listing of idTech4 tutorials.
Modding discussion
The official Blendo Discord server

Epilogue
We hope this guide helps you take your first steps into Skin Deep modding. Some of us on the team got our start in game development via modding for games such as Doom, Quake, and Half-life, so we're very proud to keep the tradition going by including mod support in Skin Deep.

Good luck, and happy modding! ✨
8 Comments
urge2splurge 9 Jul @ 5:29pm 
Fine, i'll make a map. But you arn't making this easy for me with doom 3..
Jewfro 22 May @ 3:56pm 
You can define it as a property on the door entity (ex: def_barricade func_door_barricade_blue). It will also need the barricaded property too.
Farrowe 22 May @ 9:52am 
Just a minor question:
When Setting a door to be Barricaded, how do you select which color barricade the door gets?
Goose Rider 22 May @ 12:18am 
Fantastic work guys!
Thoreaufare 21 May @ 9:35pm 
Guide looks incredibly helpful. If I ever find the time (and motivation), it'd be cool to take a crack at it.
Richard 21 May @ 8:08pm 
This is excellent, thank you
lizziekitty♥ 21 May @ 2:48pm 
<3
garbo 21 May @ 12:29pm 
Always glad to see new releases that facilitate modding, especially ones that allow you to examine and retool the original content. Thanks for making this possible