-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New Contributors Guide C structure
Warning: This is an introduction to Cataclysm: Dark Days Ahead's C++ code structure. If you're not comfortable reading C++ code, this is probably not a page you should read and you should go back to the Guide to contributing's front page.
The CDDA source code lives in the src/ directory.
I'm going to highlight some of the more important files and fundamental data structures, but again, there is a lot of CDDA code and I haven't ever touched large parts of it, so I might be missing things here.
First, some meta concepts:
- Most of the game's data is loaded from JSON using a standardized set of functions. If you're referring to this guide, you probably shouldn't be touching the JSON manipulation functions themselves. You may need to use them to load or save a particular data structure, and those functions are usually in src/savegame_json.cpp and are pretty easy to figure out. CDDA uses a complicated deferred loading structure that reads the JSON in an arbitrary order while keeping track of data structures that have unresolved references to other pieces of JSON, and then keeps reloading the JSON until the references are resolved.
-
point
andtripoint
are the fundamental data structures to keep track of 2D and 3D co-ordinates on maps. Various levels of the game's maps have different co-ordinate schemes, see doc/POINTS_COORDINATES.md for a thorough, if confusing, explanation. The most important thing to remember is that local map coordinates are always relative to the current player position on the map and change as the player moves, while global coordinates are fixed and invariant, so if you need store map coordinates for use on a future turn of the game, you must always store the global coordinates. -
- Currently,
allmany instances ofpoint
andtripoint
are the same, regardless of coordinate type, and many functions do not indicate which sets of coordinates they require or return. This is needlessly confusing and there is an ongoing project to replacepoint
andtripoint
with typed versions such asabs_omt_tripoint
. Use the typed versions whenever possible.
- Currently,
-
cata::optional
is a CDDA specific template for passing data that may be absent, such as a map co-ordinate to a building that may or may not exist.cata::optional
s are not pointers, but can usually be treated that way: checking the variable is a true/false test as to whether it has valid data, and derefencing the variable gets the underlying value if it is valid. - CDDA has a bunch of standard units defined in src/units.h with standardized, templated classes. You can do things like
units::mass weight = 3_kilograms;
for assignment, and addition and division operators are usually defined for units. Using units provides type safety when dealing with quantities and is strongly encouraged.
Here are some of the major game files and data structures. Header files usually have a matching .cpp file, and may have more than 1 related .cpp file.
-
src/game.h contains the main game loop and various global data structures. The senior developers would like to deprecate
game.cpp
, and in the meantime, do not want people adding more code togame.cpp
.Global data from theGlobal data access throughgame::
class is accessible through theg->
global pointer.g->
is deprecated to reducee overinclusion of thegame.h
header, which is slowing compile times. - The map local to the avatar is an instance of the
map::
class in src/map.h and can be accessed fromg->m
getmap()
. By convention,map &here = getmap()
is the local reference the global map around the avatar. Distant maps can be loaded for brief editing via thetinymap::
child class ofmap::
, also insrc/map.h
, andtinymap &there
is a local reference to a selected portion of the global map (analogous tohere
).map::
also contains a huge amount of terrain and furniture editing functions and general utility. -
- The local map (aka
here
orgetmap()
) is sometimes called the "reality bubble", and consists of a 121x121 square grid of tiles roughly centered on the avatar.
- The local map (aka
-
- Technically, maps consist of 24x24 map tiles, broken up into a 2x2 array of submaps containing 12x12 map tiles. Each 24x24 local map is a single tile in the overmap, and 180x180 overmap tiles form an overmap buffer, and all the overmap buffers are stored in the overmap. Each layer has its own set of source code and corresponding class.
-
src/creature.h implements the basic (and basically virtual)
Creature::
class.Creature
has two child classes:Character::
in src/character.h andmonster::
in src/monster.h. - An individual monster is an instance of the
monster::
class, and there are various monster related source files such as their AI, src/monmove.cpp and their JSON loader src/monstergenerator.cpp. All monsters of the same type share a monster type ormtype::
instance which contains the basic definition of the monster type and is coded in src/mtype.h. -
Character::
was original supposed to be a virtual parent class for its child classes, but the terminology got confusing and there is an ongoing effort to refactor them and move more code intoCharacter::
.player::
in src/player.h was originally supposed to contain data relevant to the player of the game, but it is being deprecated in favor of theavatar::
class in src/avatar.h.g->u
is the global variable for the current avatar.get_avatar()
returns a reference to the current avatar. -
- When adding new code that applies to both the player's character and NPCs, put it in
Character::
and pass variables asCharacter &
. When adding new code that only applies to the player's character, such as UI code, put it inavatar::
.
- When adding new code that applies to both the player's character and NPCs, put it in
-
- A lot of current code passes a
player &
orplayer *
when it should pass aCharacter &
orCharacter *
. In general, that pattern should not be repeated.
- A lot of current code passes a
-
- melee combat and ranged combat are in src/melee.cpp and src/ranged.cpp but the functions mostly exist inside the
Creature::
,Character::
,monster::
, orplayer::
classes, and theplayer::
functions are being moved toCharacter::
oravatar::
as appropriate.
- melee combat and ranged combat are in src/melee.cpp and src/ranged.cpp but the functions mostly exist inside the
-
- A lot of current code will do an
is_player()
oris_npc()
check before executing some code, or recast aCharacter
value intoplayer
,avatar
, ornpc
. Gating some code on a check is sometimes a clean way to implement something, but recasting variables should be avoided in favor of virtual functions inCharacter::
that are overridden inavatar::
ornpc::
and called directly and automatically.
- A lot of current code will do an
-
-
avatar &you = get_avatar()
is a preferred way to get a local reference to the current avatar, andnpc &guy
is a common way to refer to some NPC.
-
-
player::
has a child classnpc::
in src/npc.h to support NPCs. Like monsters,npc::
have a lot of support code in related files such as the AI code in src/npcmove.cpp.npc::
should not be a child class ofplayer::
but should be a child class ofCharacter::
and there is a slow migration underway to correct this. - Items, like monsters, have an item type or
itype::
in src/itype.h and an instance initem::
insrc/item.h
. Items can have more than one type, with each type containing a separateislot_
data structure in theitype::
. The current implementation ofislot_
s is not ideal and will be restructured at some point in the near future. Item definitions are loaded from JSON via src/item_factory.cpp -
src/calendar.h contains the classes used to track time in the game.
time_point
is a single point in time, andtime_duration
is the elapsed time between twotime_point
s. Like other units,time_point
andtime_duration
have addition, multiplication, and division operators defined, as well as textual assignment operators so you can dotime_duration soon = 5_minutes;
calendar.h
also has definitions for longer time periods, including seasons. - The UI is split among a variety of classes, and a lot of basic functionality such as drawing a paned window still needs to be done by hand. Menus can easily be created using
uillist::
from src/ui.h. Windows can be created and manipulated using the functions in src/cursesdef.h but a lot of window management still needs to be done by hand.
There are a lot of other classes and functions in the game: vehicle, artifacts, spells, missions, basecamps, and so on and so forth. This is only a high level introduction to get your feet wet; you'll have to read the code to understand it all. Again, git grep
or equivalent is your friend.
Back to the Guide for first time contributors