Descriptions of files in the neo/game folder.
- The name of each section refers to the C++ files (.h and .cpp) with the same name. For example, Actor indicates the files Actor.h and Actor.cpp.
- Some sections will show a file extension to mark a single file with no companion, such as Game.h.
- A "+ description" note means that the file contains a detailed description of one or several classes.
- A class name between parentheses signifies that it is inherited: SubClass (BaseClass).
- Some hypotheses are shared in this page. They are probable, but unconfirmed.
Animations, field of view, attacking and inflicting damage, footstep sounds, among many other things. The idPlayer class inherits idActor.
Hypothesis: all living characters are based on this class; perhaps also some environment objects.
AF: articulated figure (ragdoll). This file implements physics for living creatures (see the hypothesis).
For example, when an enemy is killed, it calls idAF::ApplyImpulse() to determine how the body will be thrown back by the mortal wound. If the
impulse vector in the function is multiplied by 10, the force of the push will be 10 times greater when the enemy is killed.
Hypothesis: ragdoll physics might only ever be used after the character dies, and may have no impact on animation beforehand.
This is where idAFAttachment can be found; I believe this class manages physics for the limbs ("attachments") of enemies as well as the player's.
It has a method, ApplyImpulse(), which appears to be what causes the pain reaction in enemies when they've been shot two or three times; the function is only called when the player successfully hits the enemy a number of times.
If, for example, the
impulse vector in the function is multipled by 100, then after a few shots in the arm, the enemy will be abruptly pushed far away (though it probably won't take extra damage), as the arm pulls the rest of the body back with it.
Other classes also make use of ragdolls: idAFEntity_Generic, idAFEntity_WithAttachedHead, idAFEntity_Vehicle, and others.
Glass, usually, or any surface that can be shattered. When a window receives a few hits, it breaks into many shards with idBrittleFracture::Shatter(). This class is what the func_fracture entity is based on.
This file holds three classes: idCamera (abstract), and its subclasses idCameraView and idCameraAnim, so when a subclass calls its Spawn() method, it also calls idCamera::Spawn(). Strangely, idCamera's implementation does nothing; perhaps it was used for testing.
- idCameraView is the class behind the func_cameraview entity in DarkRadiant.
- idCameraAnim is a camera that moves along a line (spline).
While there is an idTarget_EndLevel class defined in EndLevel.h and EndLevel.cpp, neither of these files is included in the Game project.
See Target.h and Target.cpp, where its final version is stored.
(idTarget_EndLevel is the class that powers the target_endlevel entity.)
The base class for all entities. It creates and updates entities, plays sounds, etc.
Each instance has an idDict object called
spawnArgs. It is a list of the entity's parameters and their values on map load; in other words, the properties given to it during level editing (
- idEntity::CheckDormant() is called every frame. It calls DoDormantTests() to know if the entity should be "awake", which means it should act the way the player expects.In the case of monsters, for example, this generally means walking around and attacking when they spot the player. If there's no chance of interaction between the player and the monster, it will stay dormant, in order to save system resources.
- idEntity::DoDormantTests() checks the
fl.neverDormantflag (which reads the entity's
neverDormantspawnArg in Spawn().
- I believe idEntity::Event_UpdateCameraTarget() updates the camera view on in-game screens.Note: This function has a strange line of code; it seems that the function takes the orientation of every camera and applies it to all entities that are linked to it via the
The line is inside a loop:
while( kv )
SetAxis(dir.ToMat3()); // This line causes strange rotations
The usefulness of this line is uncertain, so I've commented it out to stop the rotations, and have not had problems.
idEntity::SetModel( const char *modelname ) associates a (static) model with an entity ; most models used are in ASE or LWO format. This method is not used for animated MD5 models.
Note: there are references to such models as "grenadeExplosion.prt". There are no files with this name in Doom 3's resources;
grenadeexplosionis a particle effect defined in particles/explosions.prt. The approach used to load particle effects is somewhat nebulous.
Instances of idEntityFx read .fx files to create special effects. Many .fx files can be found in base/pak000.pk4, in the fx folder.
Like many non-"local" classes, idGame is abstract and only serves as an interface to a "local" object, in this case idGameLocal. There is a Game_local.cpp, but no Game.cpp.
According to Fabien Sanglard's Doom 3 source code review, the engine and game communicate at the startup of the application with a global function called GetGameAPI() (in neo/game/Game_local.cpp).
idGameLocal may be the most powerful and important class in Doom 3. It inherits idGame, and holds a number of methods for accessing information from various parts of the engine.
- idGameLocal::FindEntity() returns an entity with the specified name (or
Notable member variables:
entitiesis an array containing all entities in the level. It has a size of 4096, which is the maximum number of entities that can be in a map; if the map contains fewer entities, the remaining ones in the array will be
is the number of milliseconds elapsed since the start of the level.
This file implements idGameLocal's networking-related methods.
The idDragEntity class allows the player to drag visible entities (objects, corpses) when the g_dragEntity CVar has a value of 1. The movement of these entities will be physically realistic, and corpses for example can be dragged by their joints (head, arm, leg). Its Update() function is called every frame when
g_dragEntity is set to 1, whether an entity is being dragged or not.
idCursor3D draws the yellow and red arrows when an object is dragged with its Present() method, which presents graphic information to the renderer.
With the idEditEntities class, it is possible to display graphical debug information by giving the
g_editEntityMode CVar a value from 1 to 7. Each value will allow editing for a different entity type: lights, sounds, articulated figures, particles, etc.
Inverse kinematics for walking.
Objects that the player can take. The most important function is probably idItem::Pickup() which plays a sound and makes the item disappear when it is touched.
Visible, electric lights in the levels. For example, when a fluorescent light is destroyed, idLight::Killed() is called.
=Misc (+ description)
This file groups a number of small classes, such as:
- idActivator: an invisible object that can activate triggers; supports the func_activator entity.
- idAnimated: animated entities; supports a number of entities.Note: Strangely, monsters don't seem to call idAnimated::StartRagdoll() when they are killed.
- idEarthQuake: a map-shaking effect; supports the func_earthquake entity.
- idFuncPortal: uncertain. The description of the entity powered by this class, func_portal, reads "Use to make triggerable portals." However, its material (
textures/editor/visportal) points to a relation to vis portals.
- idPathCorner: comment: Path entities for monsters to follow.
- idPlayerStart: spawning position for the player; supports the info_player_start entity.
- idShaking: a shaking object, which can hold a visible model; supports the func_shaking entity.
- idSpawnableEntity: a very simple entity that can be used to signify a location in a map, or contain a non-interactive model, among other things.
- idTextEntity: displays text in a map; supports the "text" entity.
Small moveable objects, like ordinary boxes.
Following a few tests, I've found that idMoveable::Collide() is called every time a moveable object collides with the ground or walls while moving. This function is called many times when the object is moved, so it is difficult to tell if collisions with the player are treated the same way.
The idBarrel and idExplodingBarrel classes, in the same files, inherit idMoveable.
Various moving objects. There are several classes:
- idMover and its subclass, idElevator.
- idMover_Binary and its two subclasses, idDoor (func_door entity) and idPlat (func_plat entity) ; objects that can only move in two directions.
- idMover_Periodic and its subclasses, idRotater, idBobber, idPendulum and idRiser ; objects with (potentially) neverending movement.
Framework for a multiplayer game.
Note: The game et d3xp (Resurrection of Evil expansion) folders have numerious files with the same name, but not all of these files are identical.
The MultiplayerGame.h/cpp files are different in the d3xp folder. The d3xp version checks a number of times that the
CTF (Capture the Flag) and
_D3XP constants are defined and runs additional code if they are.
The player. Two classes are defined here: idInventory and idPlayer.
idInventory appears to track the player's health, weapons and armor.
idPlayer is a massive class, with many properties and member functions:
- idPlayer::DrawHUD() draws the updated HUD every frame (cursor, health, etc.).
- idPlayer::EnterCinematic() places the player in a "cinematic" state (by freezing movement with
physicsObj.SetLinearVelocity( vec3_origin );) and turning the model invisible.
- idPlayer::Killed() makes the player model go into ragdoll mode before the Game Over screen.
- idPlayer::Move() manages animation (idle, running, etc.) and character movement.
- idPlayer::PerformImpulse() detects commands (or impulses) associated to certain keys (and mouse buttons) and calls idPlayer's related member functions. (Impulses are defined in neo/framework/UsercmdGen.h).
- idPlayer::ShowTip() displays a message in the hud (hud.gui).
- idPlayer::UpdateDeathSkin(): I'm not sure what this method is supposed to do; it may be useful in multiplayer mode, if opponents disintegrate like enemies.Note: This function has caused problems in the past. When
UpdateDeathSkin( false )is called upon death, the player model's arms disappear.
- idPlayer::UpdateWeapon() : one of the purposes of this function is to find out if the player is interacting with a gui or talking with an ally, before allowing the player to fire their weapon (see Weapon_Combat(), Weapon_GUI() et Weapon_NPC()).
- idPlayer::Weapon_Combat() manages the weapon's state: reloading, weapon change, and firing (in that order).
- idPlayer::Weapon_GUI() is called when the player interacts with a gui on a screen.
- idPlayer::Weapon_NPC() is likely called when the player clicks on an NPC.
- idPlayer::WeaponFireFeedback() shakes the player's view when a shot is fired.
Notable member objects:
godmodegrants invulnerability and can be toggled with the
noclipstops the player from colliding with the environment and can be toggled with the
Uncertain, but probably the player icon in multiplayer mode. In PlayerIcon.h, there is an enum called playerIconType_t which contains three values:
ICON_NONE. These names imply that this class mostly serves in online play.
idPlayerView manages the various effects and filters that can change the player's view.
- idPlayerView::SetPlayerEntity() sets the player that whose view will be affected (possibly variable in a multiplayer game).
- idPlayerView::DamageImpulse() thrusts the view to the side when the player is hit.
- idPlayerView::WeaponFireFeedback() is called by idPlayer::WeaponFireFeedback().
- idPlayerView::RenderPlayerView() renders the scene from the camera's viewpoint.
Notable member objects:
- The screenBlob_t struct is for screen filters like claw marks.
Bullets fired in Doom are instances of idProjectile; the handgun creates only one every shot, whereas the shotgun creates several. It has subclasses: idGuidedProjectile and idBFGProjectile.
There are also a few other small projectile-related classes.
PVS = potentially visible set, as stated in neo/game/Game_local.h:
idPVS pvs; // potential visible set
Security cameras can display what they see on screens elsewhere in the map; they aren't used extensively in Doom 3.
- idSecurityCamera::Killed() is called when the camera receives a certain amount of damage and "dies".
- idSecurityCamera::Think() is called every frame whether the camera is sweeping (and rotating) or not.
- idSecurityCamera::StartSweep() starts the camera's rotation.
There is a technical problem with security cameras: they always target a direction completely different from their model. Apparently, the error may be in idSecurityCamera::Event_ContinueSweep()...
What exactly these files do is unclear, since they don't seem to affect smoke in the game (after erasing the contents of every function in the class, smoke was still present and still functioned well in the game).
idSmokeParticles isn't an abstract class, and it doesn't seem to be inherited by anything.
A rather small class, idSound powers the "speaker" entity. (The sound system is set up in neo/sound/snd_system.cpp.)
idTarget represents entities whose names start with target_. These entities have diverse utilities:
- target_null: generic target for cameras.
- target_light_fadeout: for making a light go out slowly.
- target_lock: locks or unlocks a door.
target_ entities can be activated by an entity of type trigger_ (see just below).
Trigger entities execute predefined actions when something touches them.
Many classes inherit idTrigger:
- idTrigger_Multi::Event_Touch() is called when the player enters the trigger.
- idTrigger_Multi::Event_Trigger() is called if the trigger has a
targetproperty. If this property's value is the name of a trigger_relay (or an object of similar type), the
callproperty of this trigger_relay will be searched for a script function to execute.
idweapon is the base class for all weapons: it uses an enum called weaponStatus_t to determine the weapon's current state (WP_OUTOFAMMO, WP_RELOAD, WP_HOLSTERED...) and holds quite a few functions, a few notable ones being BeginAttack() et EndAttack().
BeginAttack() is called upon pressing the left mouse button, and EndAttack() on release. This allows the player character to continuously fire until the button is released, even for semi-automatic weapons.
Note : For some reason, BeginAttack() is called more than once for every shot fired.
The "worldspawn" entity represents the entire level.
- idWorldspawn::Spawn() sets the gravity (
g_gravity) and lowers stamina (
pm_stamina) to zero if we're in a Hell level.