-
Notifications
You must be signed in to change notification settings - Fork 6
Doc_Code_CodingStandards
When it comes to general C/C++ code, Bungie uses a lower-underscore-case. Eg, object_create
. All words in it are lowercase, and the underscore is used for separating those words. From Halo2 and onward, they started using a subset of Hungarian notation for types:
- class:
c_this_is_a_class
- struct:
s_this_is_a_struct
- enum:
e_this_is_an_enum_typename
- constant:
k_i_am_a_named_constant
For non-POD types they prefix members with m_
(eg, m_definition_index
). I've also seen cases where they use the g_
" prefix for global variables.
For enumeration types, the typename will be prefixed with e_
. Members of the enum wll be prefixed with the typename, sans the initial e
. For members which describe a bit index, they typically postfix the member name with _bit
. For members which describe a series of flags, I recall seeing them use _flags
before as a postfix.
Like say, these are conventions used with the start of Halo2. With Halo1, they were still only using C in the engine code (albeit, the tools had some C++ code). Many of these conventions weren't followed at the time because they didn't have fancy pants classes and such.
And of course, they also use SCREAMING_CAPS
for macros definitions.
When it comes to C++ based code, we typically follow the same conventions, with a few differences. Where Bungie doesn't use namespaces (as far as I've seen in their production code), we do. For the most part, we also use pascal case for our functions and namespace names. Usually when they're not directly related to reverse engineered Bungie code anyway. There are some exceptions (see EngineFunctions.hpp
).
We also keep enum values tucked away in a nested "Enums" namespace. The same goes for bit/flag enumerations, but in a "Flags" namespace.
For typedef's we postfix the typedef name with _t
to keep in line with the standard template library, such as this_is_a_typedef_t
.
Class and struct names should use lower-underscore-case with a prefix indicating their type. For instance i_configuration_leaf
or c_configuration_container_list
-
c_
for classes -
i_
for interfaces -
s_
for structs
When defining classes in headers we use the following format:
#!cpp
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Abstract list object for a list of configuration values. </summary>
///
/// <typeparam name="T"> The configuration value type. </typeparam>
template<typename T>
class c_configuration_list
abstract
: public i_configuration_value
{
Since C++11 we have been using the final
and override
keywords in our classes and member functions, you should too. Also, auto
is love, auto
is life.
When it comes to const correctness I (TheFieryScythe) tend to const all functions and their parameters wherever I can.
We tend to follow the conventions used by the .NET framework itself. However, for newer code (anything made after 2009) we've started to use m_
prefixes for non-public member data (some of the .NET framework's internals do this, other parts don't). We also use a k
prefixed for literals as well (still pascal case after the k
though)
Our in-code documentation of functions is handled using Atomineer Pro Doc. It is a paid product, but it's such a time saver in making documentation quick to add and consistently formatted we find it's worth the cost.
Our documentation across the board has not been converted to a single style yet, that's work in progress. So to save confusion this is the style we are using:
#!cpp
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Makes a unit exit it's current seat. </summary>
///
/// <param name="unit_index"> Zero-based index of the unit. </param>
/// <param name="force_state">
/// (Optional) Whether to force the idle state so that the unit is guaranteed to exit
/// gracefully.
/// </param>
/// <param name="force_exit">
/// (Optional) Whether to forcibly remove the unit from the seat.
/// </param>
void UnitExitFromSeat(const datum_index unit_index
, const bool force_state = false
, const bool force_exit = false) const;
-
assert(x)
- CRT assertion. Only present in _DEBUG builds -
YELO_ASSERT(x)
- Sort of a misnomer. Maps to the blam'sASSERT
constructs. These are technically only available in editor builds.YELO_ASSERT
's are compiled no matter_DEBUG
's definition -
ASSERT(x, msg)
- Yelo'sASSERT
macro that exists in both runtime and editor builds, and includes a custom message parameter (string). Only compiled inAPI_DEBUG
builds
-
Use this to assert logic that is truly debug related, esp. to the development of OS
-
...and when it can't be triggered from user input
For example, in CheApe
assert()
is used to verify group definitions (seeEngine/AnimationUpgrade.cpp
) as these are set in stone. -
...and will always be executed (assuming the macro expands to anything).
For example,
tag_group_memory.cpp
builds extra data from group definitions (mostly set in stone, CheApe.map is the exception). There's no code path which skips the initialization of tag groups, so as long as this system is enabled this code, and theassert()
's, will be executed
- This is mostly for editor/CheApe-only code (as it expands to calls defined in
Engine/EngineFunctions.cpp
)
- This is mostly for runtime code
- Use for code which is compiled in both runtime/editor builds (will expand to
YELO_ASSERT(x)
in CheApe)
- Filenames should be lowercase and use underscores instead of spaces
-
_definitions
use this postfix for data (namely tag) struct definitions. Eg,unit_definitions.hpp
-
_structures
use this postfix for runtime struct definitions. Eg,unit_structures.hpp
-
_system
use this postfix for game systems which have an a lot of system definition code (ie, initialize, dispose, etc) on top of regular system interface code (egsome_data_get_id()
). Eg,tag_groups_system.cpp
- Filenames should be Pascal cased, ie each first letter is uppercase, no spaces. This is mostly just as a way for telling open files apart
When writing systems using classes it is preferred for each class to be in it's own file, with the file name being the same as the name of the class.
-
Wiki Home
- Halo 1
- FAQ
- Getting Started
- Related Forum Threads (Legacy)
- Post-Mortem
- Gamers
- Modders
- Server Hosts
- HTTP Server
- Map Download
- Programmers