### General rules * Do not change code already written unless it's related to your contribution or absolutely needed. * Please check and try to eliminate warnings from your code. ### Code style * 4 space indentation, LF line endings * No hungarian notation [It's useless] * In classes, use `m_` prefix to nonstatic member variables and `ms_` for static members. Do not use a prefix in structs. * Use `s_` for global variables that are only used in one source file, otherwise use `g_`. * If some rule about something is not specified here, refer to how it's done in the code * Some classes may have *helper* functions to make code more readable. (Denoted by *NOTSA*) - Try adding new ones, or looking for and using them. * If you made *helper* functions in a source file, mark them as `static`. * Prefer `get`-ters/`set`-ters over raw member access * Use range-based for loops as much as possible. * Use `ranges` versions of `std` functions as much as possible. * Use `rng::` instead of `std::ranges` and `rngv::` instead of `std::views`. * We encourage you to write modern C++, but if that's not your style, please keep the following in mind: * Use `ranges` versions of `std` functions as much as possible. * Use `rng::` instead of `std::ranges` and `rngv::` instead of `std::views`. ```cpp for (auto& element : array); // <-- GOOD for (int i = 0; i < std::size(array); i++); // <-- BAD ``` * Use `rngv::enumerate` if you need both the index and object. ```cpp for (auto&& [i, e] : rngv::enumerate(array)); ``` * If there's a dynamic `count` variable associated with a fixed size array, use `std::span` or `rng::views::take`. E.g.: ```cpp // Bad for (auto i = 0u; i < m_numThings; i++); // Good for (auto& thing : std::span{ m_things, m_numThings }); // Also good for (auto& thing : m_things | rng::views::take(m_numThings)); // ^ If these funcs are called more than once, make a helper function in the header. Like below: auto GetActiveThings() { return std::span{ m_things, m_numThings } } ``` * Use `f` in float literals [As omitting it would make them a `double`] (e.g. `1.0f`) * Use `std` library for generic functions like `min`, `max`, `lerp`, etc... * `CVector` is interchangible with 3 floats [As is `CVector2D` with 2 floats] for function args * Use lambdas for repetitive procedures in functions * Use `constexpr` variables instead of macros * Use `static inline` instead of `extern` and `static` in headers: ```cpp class Foo { static uint32& m_FooCount; // Bad static inline auto& m_FooCount = StaticRef(); // Good } ``` #### Types * Use `auto` in function bodies if the variables' type is guessable. * Guess for enum values [Or at least leave a `TODO` comment] * Take care of const correctness [Especially of class methods] (e.g. `const char*` over `char*`) * Try to use SA types over RW as much as possible, **except** `RwMatrix`. (e.g. `CVector` for `RwV3d`, `CRGBA` for `RwRGBA`) * Use fixed width integer types (e.g. `uint8`, `int32`). * Do not use Win32 integer types. [Except for Win32 exclusive code] (e.g. `DWORD` -> `uint32`) * For array sizes, etc... prefer using `unsigned` types over `signed` ones * Whenever possible use `std::array` over `C-Style` array [as the former has bounds checking in debug mode, and can help us discover many bugs] #### Fixing bugs Whenever you find a bug, we encourage you to fix it [and/or at least] leave a comment explaining what the bug is. Bug fixes should only be active if `notsa::IsFixBugs()` returns `true`. If that's not possible [due to code complexity], then wrap into an `#ifdef`: ```c #ifdef FIX_BUGS // Bug fixing code here #endif ``` ### Handling translated (GXT) text * GXT code page is a partial superset of ASCII, it's one-to-one except for `^`, `[` and `]`. (translated to [`ยก`](https://en.wikipedia.org/wiki/Inverted_question_and_exclamation_marks), `<` and `>` respectively) * GXT encoded characters are 1-byte long and strings are null-terminated. They can be used in `char` typed C copy/compare functions. * Do not assume anything other than above for GXT strings. * Use `AsciiToGxtChar` and `GxtCharToUTF8` for safely converting. UTF-8 strings should be safe to print and manipulate in general. * Use `AsciiFromGxtChar` (or `""_gxt` for literals) and `GxtCharFromAscii` for implicitly converting. You **must** be sure that all characters are ASCII. ### Contributing Please make sure to test your code before opening a PR. Guess what places/missions are affected by your code and test them. Use debug menu (F7) for quick access to stuff. If you don't know how to test the code or think you have not tested enough specify it in the PR message.