User:SirYodaJedi/Porting IdTech 3 maps to Source
It contains the advice or opinions of one or more of the Valve Developer Community's contributors.
This page is not an encyclopedia article, nor is it one of the Valve Developer Community's policies or guidelines, as it has not been thoroughly vetted by the community.
Some essays represent widespread norms; others only represent minority viewpoints.
![Under construction icon-blue.png](/w/images/thumb/d/df/Under_construction_icon-blue.png/32px-Under_construction_icon-blue.png)
Remember to check for any notes left by the tagger at this article's talk page.
![Info icon Info icon](/w/images/thumb/b/b3/Info.png/32px-Info.png)
This page attempts to document the fiddly process of converting a map from a id Tech 3 game to a
Source game. This guide will demonstrate it by porting the
Wolfenstein: Enemy Territory map "Würzburg Radar" to
Day of Defeat: Source, as the two games core game modes are similar, the original map sources are officially publicly available, and most of the necessary auxiliary assets are provided with GTKRadiant (with the missing ones found in this repo).
Getting started
Skills required
This article assumes some familiarity with the following skills:
- Mapping
- Basic 3D model editing
- Image manipulation and conversion
- Audio conversion and looping a sound
- The command-line interface
Installing tools
Required tools:
- The original game (duh)
J.A.C.K. - Can convert the Id Tech 3 map files to
GoldSrc format, as well as export as VMF
GtkRadiant - has a lot of models and material information that aren't present in the games' files, due to being baked into the BSP. It also includes Q3MAP2, which can decompile maps you don't have the source MAP files for.
NetRadiant-Custom - it's fork of Q3MAP2 may be preferred for decompiling maps, as it supports Valve220, allowing for more accurate texture mapping. Additionally, it can convert IdTech 3 maps to OBJ, instead of only MAP or the ill-supported ASE.
Blender - Can do necessary fine-tuning to the converted models, as well as do the conversion itself with the proper plugins. The following plugins are used:
- Blender Source Tools - SMD import and export support
- RtCW:ET Blender Model tools - MD3, MDC, MDS, and MDM/MDX import and export.
Important:For plugin compatibility reasons, this guide uses Blender 3.1.1. Any version between 2.92 and 3.1.1 should work, but newer versions may have issues.
GIMP - Assorted texture manipulation.
Photoshop can also be used, but this guide focuses on the free option.
Additional useful tools
TrenchBroom - Can export the unconvertible patch meshes to OBJ, which can be used as a prop_static.
- Noesis - Can open most relevant models, except MDC. SMD export has flipped UVs and lacks animation; use FBX instead.
- Half-Life Quake3 Map Converter - can allegedly be used instead of Jack for map format conversion, but is older and untested, and creates a MAP instead of a VMF (not to mention, is Windows-only).
7-Zip (or WinRAR) - Preferable for extracting PK3s. Much faster than using Windows's built-in ZIP extractor, and doesn't require renaming the file extension.
Preparing workspace
To start, it will be necessary to decompress the PK3 archives containing the game assets.
- Create a new folder which will house the assets. This should be separate from the game installation, for example
D:\Applications\IdTech 3 Modding\Wolfenstein Enemy Territory\
. - Inside the newly-created folder, create a folder with the same name as the game's PK3s are contained in. For example
D:\Applications\IdTech 3 Modding\Wolfenstein Enemy Territory\etmain\
. This will be henceforth referred to as the source asset directory. - If the game has any subfolders inside the folder containing the PK3s, copy those folders to the source asset directory.
- Extract all the PK3s from the original game to the source asset directory.
- In the GTKRadiant folder, navigate to the
installs
subdirectory. This contains the "game packs" which have the necessary auxiliary assets.
Note:GTKRadiant 1.6 is missing the Jedi Outcast game pack. This will need to be downloaded separately; it can be found in GTKRadiant 1.4.
Note:The Wolfenstein: Enemy Territory game pack is missing several map prop models; this can be found separately.
Todo:
Decompiling maps
It is preferable to work from source map files, when available. Compiled id Tech 3 maps don't (usually) have lighting entities, and lightmapped models are embedded into the map's mesh data. When a map is decompiled, the embedded models are removed, no lighting data is available, .
![Note.png](/w/images/thumb/c/cc/Note.png/10px-Note.png)
Nonetheless, map sources are frequently not available, leaving no other option. Fortunately, Q3MAP2, the same compiler used to compile id Tech 3 BSPs, can also decompile them! The following command will decompile the map into a format that can be properly edited:
q3map2 -game xxxx -convert -format map mapname.bsp
![Note.png](/w/images/thumb/c/cc/Note.png/10px-Note.png)
As this doesn't include embedded models, it often is also necessary to convert the BSP to a 3D model. NetRadiant-Custom's Q3Map2 supports converting the BSP to OBJ, as such:
q3map2 -game xxxx -convert -format obj mapname.bsp
![Note.png](/w/images/thumb/c/cc/Note.png/10px-Note.png)
![Tip.png](/w/images/thumb/4/45/Tip.png/9px-Tip.png)
![id Tech 3](/w/images/thumb/d/d9/Quake3-16px.png/16px-Quake3-16px.png)
![Source](/w/images/thumb/1/10/Icon-Source.png/16px-Icon-Source.png)
Keep static prop lighting limitations in mind if doing this; consider prebaking lightmaps into the $basetexture or a Modulate overlay if not using
![Source 2013 Multiplayer](/w/images/thumb/1/11/Src13mp-16px.png/48px-Src13mp-16px.png)
![Note.png](/w/images/thumb/c/cc/Note.png/10px-Note.png)
![Blank image.png](/w/images/b/ba/Blank_image.png)
![Note.png](/w/images/thumb/c/cc/Note.png/10px-Note.png)
Converting uncompiled map files
![Blank image.png](/w/images/b/ba/Blank_image.png)
- Using Jack to create a VMF with the brushes and entities, and a MAP file with just the patch meshes
- Using Q3Map3 from NRC to convert the patches-only MAP directly to OBJ (which does work, unlike BSP to ASE/OBJ)
Converting materials
![Tip.png](/w/images/thumb/4/45/Tip.png/9px-Tip.png)
Converting textures
Choosing the right image format
![Blank image.png](/w/images/b/ba/Blank_image.png)
- IdTech 3 supports texture compression, but not all versions used pre-compressed textures, instead using JPG, TGA, and sometimes PNG.
- Not all GPUs supported texture compression back in 1999, so it was done on-the-fly and is able to be disabled. Most people disable it nowadays, as VRAM is much more plentiful, and the benefits of disabling are apparent on low-res textures.
- In RtCW, WolfET, and possibly other games, textures with resolution of 128x128 or lower are never compressed.
- Some games used DDS. If it is necessary to use a DDS texture as a source, use the same image format as the original texture if possible. For example, VRAD has a bug where it can't read the alpha channel from DXT3 textures for generating texture shadows, so it will be necessary to use DXT5 instead.
- In Medal of Honor: Allied Assault, the DDS versions are allegedly higher resolution than the TGA/JPG versions; I don't have MoA:AA, so I can't confirm this.
Selecting material parameters
See User:SirYodaJedi/Porting_IdTech_3_maps_to_Source/Shader2VMT
Replacing tool textures
IdTech 3 | Source | Notes |
---|---|---|
common/caulk | tools/toolsnodraw | |
common/nodraw | tools/toolsinvisible | |
common/hint | tools/toolshint | |
common/skip | tools/toolsskip | |
common/trigger | tools/toolstrigger | |
common/areaportal | tools/toolsareaportal | |
common/origin | tools/toolsorigin | Deprecated; preferably delete and set the origin KV. |
Converting models
MD3, MDC, MDS, MDM/MDX
- In a version of Blender from 2.92 to 3.1.1, install RtCW:ET Model tools v1.0.0_rc3 and Blender Source Tools v3.2.5.
- Open a new workspace in the selected version of Blender. Delete the default cube.
- Press N to open the sidebar, then switch to the "RtCW/ET" tab.
- In the import section, select the source format and file path, then press the import button.
- For each mesh, select it, right click, and choose shade smooth.
- Check the skin file and check if any skins are set via mesh name, instead of via material name. If so, reassign materials accordingly.
- Export the collection as SMD. This will convert split edges to sharp edges, to make things easier to edit.
- Open a new workspace, then reimport the SMD.
- Unflag sharp edges as desired. The importer generates accurate normals, but the normals of vanilla models aren't too pretty to begin with.
- When writing the QC file, put $origin 0 0 0 270 so that the model is rotated correctly.
ASE, LWO
![Blank image.png](/w/images/b/ba/Blank_image.png)
MDR, GLM
![Blank image.png](/w/images/b/ba/Blank_image.png)
- Use Noesis to convert the models to FBX.
- Noesis can export directly to SMD, but the UV map will be flipped vertically (I reported this bug to the creator, but he refused to believe the current behavior was incorrect).
Confirm: Do animated props need to be converted via a different method?
- Import to and export from Blender. Editing can be done, if necessary.
- For static props in
Source 2013 Multiplayer, it may be desireable to redo the model's UVs so that everything is on one texture, and no UVs are overlapping or tiled. This allows model lightmapping to be properly used, as model lightmaps use the same UVs as the $basetexture.
- For static props in
- Write QC files.
- Compile.
Crowbar can be used as a handy frontend for compiling.
Skin files
Unlike the baked index tables in Source, IdTech 3 uses loose .skin files to change a model's skin.
- Skin files are formatted similarly to CSV files. Each line contains an internal name, followed by the material (or opaque texture) to remap to. Confusingly, the internal name can refer to either an actual material (or opaque texture) name, or a mesh name.
- Occasionally, skin files will also be used to define what model to put at an attachment. This is usually only used on character models, and the actual attachment names (from a TAG file; see the documentation for the RtCW:ET blender tools) aren't always used, but instead are set via game code.
Converting sounds
For the most part, sounds from id Tech 3 games can be used in Source without much hassle as long as they are converted to a compatible format (if they aren't already). The exception, of course, is looped sounds. Unlike id Tech 2 and Valve's engines, id Tech 3 does not require WAV cue points for looped sounds. This means that cue points must be added, and non-WAV sounds that are looped must be converted to WAV, which greatly increases file size.
Converting map content
Entities
A few entities in IdTech 3 have analogous entities in Source 1.
![]() |
![]() |
Notes |
---|---|---|
func_group | N/A | Func_group brushes should be untied from entities and returned to worldspawn, as VBSP lacks func_group support. If the brush had the detail flag, tie to func_detail instead. |
misc_model | prop_static | Unlike prop_static in Source 1, misc_model in IdTech 3 can be lightmapped in the same way as brushes. This is done sparingly, via spawnflag 2 "force meta" or material command q3map_forceMeta, as it basically converts the model into trisoup brushes. Most small or medium-sized misc_models are lit about the same as prop_static (with Q3Map2 doing bounced lighting on them like CSGO). ![]()
|
misc_model_static | prop_static | In Jedi Academy. Like misc_model, but the model is rendered as a runtime entity, instead of baked into the map geometry. If you want to be accurate to how this affects lighting, you could disable per-vertex lighting. |
misc_model_ghoul | prop_dynamic | In Jedi Outcast and Jedi Academy. Arbitrary animated GLM model; destroyable. |
misc_model_* | prop_dynamic | In Raven Software games. Specific MD3 model to display at runtime, sometimes animated; see DEF or ENT entity description file for model path and usage specifics. |
misc_gamemodel | prop_dynamic | In RtCW and WolfET. ![]() |
script_model_med | generic_actor monster_generic |
In RtCW and WolfET. A model which has its animations and movement defined in an external script file. |
dlight | light_dynamic | Flickering light. Only affects dynamically lit models; set the "Do not light world" flag to be accurate. |
lightJunior | N/A | Only affects dynamically lit models, and does not use an edict. Source 1 and its BSP format technically supports this, but the compilers lack a way to set it, so you'd have to manually edit/replace the WORLDLIGHTS and WORLDLIGHTS_HDR lumps. |
info_null | info_null | This is usually the same thing.
The exception is in WolfET, where the entity is kept around for a tick longer than usual. This is done to allow game entities to target the point; to mimic this behavior, killtarget the entity with a logic_auto 0.1 seconds after map spawn. |
info_camp | info_null | Basically the same thing. |
info_notnull | info_target | Works the same way; Valve decided to rename the entity in GoldSrc. |
target_position | info_target | Same as info_notnull. |
target_relay target_delay |
logic_relay | Only difference between relay and delay is whether the target is triggered immediately or after a delay. The delay can have a random variance to it, in which case some complicated logic_timer shenanigans may be necessary, probably in conjunction with a logic_case. |
func_timer | logic_timer | Despite the func_ prefix, this is a point entity. |
trigger_always | logic_auto | IdTech version is poorly named. It is only fired on map spawn, but does not fire if a map is entered from a level change without starting a new unit. As such, it might be necessary to ![]()
|
target_speaker | ambient_generic | |
info_player_intermission | ![]() ![]() |
Controls camera in between rounds.
![]() |
misc_portal_surface | func_monitor (if has target) func_reflective_glass (if no target) ![]() ![]() |
Point entity which affects the nearest portal surface, which will need to be turned in to the appropriate brush entity. |
misc_portal_camera | point_camera | Target for the misc_portal_surface. |
team_CTF_redplayer team_CTF_redspawn |
![]() ![]() ![]() ![]() ![]() |
In Quake III (and maybe RtCW?), the team_CTF_*player are initial spawn points, whereas team_CTF_*spawn are respawn points. WolfET always uses the latter; toggling them based upon conditionals. In RtCW and WolfET, red is Axis (German), and blue is Allied (American). |
team_CTF_blueplayer team_CTF_bluespawn |
![]() ![]() ![]() ![]() ![]() | |
team_WOLF_checkpoint | ![]() |
In WolfET. A checkpoint, flag, command post, or control point; whatever you want to call it.
|
Notable KVs
Some KVs that are common across several entities
- angle (integer) - Yaw rotation. For example, a misc_model angle of "180" is equivalent to a prop_static's angles of "0 180 0".
- target (target_destination) - send an input to the specified entity (whatever that entity's "do" input is)
- targetShaderName (material) + targetShaderNewName (material) - When triggered, the specified material in the target entity with a different material. Note that targetShaderName will always be the original material name, even if the material being displayed has been changed at runtime. This will require some complicated material proxy stuff env_texturetoggle or material_modify_control on brushes, but on prop_dynamic, you can just send the skin input.
- model2 (model path) - The first frame of a dynamically-lit model is displayed at runtime wherever this brush entity's origin is (which will move if the entity moves). Put a prop_dynamic where the origin is, and parent it to this entity.
- modelscale (float) - Uniform scale of the model (or for brush ents, model2) in all directions. Depending upon the engine branch and entity, you might be able to do this in the entity's properties, but otherwise you can use $scale.
- modelscale_vec (X Y Z vectors) - Per-axis scale of the model (or for brush ents, model2). This can't be done with entity KVs or $scale, so it will need to be done in Blender.
- skin (skinfile path) - A .skin file to use for the models skin. See #Skin files.
- _castShadows, _cs (boolean) - Whether entity casts lightmap shadows. See vrad_brush_cast_shadows for brush entities, or disableshadows for prop_static.
- _lightmapsamplesize, _samplesize, _ss (integer) - Explicit luxel scale.
- _lightmapscale, lightmapscale, _ls (float) - Adjusts luxel scale relative to the material's q3map_lightmapSampleSize, or, if not present, the -samplesize Q3Map2 parameter). If neither are present, assume a default luxel scale of 16. Do note that brush/disp lightmaps in Source are much lower resolution than lightmaps in Quake 3 (32px vs 128px+), so to avoid excessive subdivision on really low luxel scales, consider using static prop lightmaps if possible.
- _remap* (string "original_material;new_material") - The first material is replaced with the second material in the compiled map (usually used for misc_model). Use skins.
- _shadeangle, _smoothnormals, _sn, _sa, _smooth (degrees) - any angles equal to or more obtuse than this value are phonged together. Use smoothing groups as deemed suitable. If this is on worldspawn, use the -smooth n VRAD parameter, wherein
n = 180 - q
, with q being the q3map2 shade angle.
Terrain
Patch meshes
![Blank image.png](/w/images/b/ba/Blank_image.png)
- Use models
- Recreate as displacements (if possible; not possible if tied to entity)
- Convert to brushwork, using OBJ2MAP or similar (if practical)
![Note.png](/w/images/thumb/c/cc/Note.png/10px-Note.png)
External links
- Porting Quake 3 Maps to Source on the
Momentum Mod documentation (only covers map geometry and textures; does not cover patch meshes)
- Pcpie' tutorial on porting Quake 3 Maps to Source on GameBanana (only covers map geometry and textures; does not cover patch meshes)
- Q3Map2 manual - Discusses how to compile a model from a MAP; essential for porting patch meshes, which cannot be ported directly, and instead need to be either recreated as displacements (when possible) or static props.