Imported from aglowinthefield/mo2-fomod-plus (
AGENTS.md). Install upstream withnpx skills add aglowinthefield/mo2-fomod-plus. Copyright stays with the author.
Repository Guidelines
Project Structure & Modules
- Root
CMakeLists.txtbuilds two MO2 plugins:installer/(fomod_plus_installer) andscanner/(fomod_plus_scanner); both share helpers ininstaller/lib/andshare/. - UI assets live in
installer/resources/andscanner/resources/; translations are.tsfiles in each module and packaged.qmfiles underpackage/translations/. - Tests sit in
tests/with XML fixtures intests/moduleconf/; packaging output lands inpackage/plugins/. - Clone this repo inside
build/modorganizer_super/<repo>of your mob checkout so MO2 headers and dependencies resolve.
Build, Test, and Development Commands
- Configure (uses local paths in
CMakePresets.json):
cmake --preset vs2022-windows - Build (RelWithDebInfo by default):
cmake --build vsbuild --config RelWithDebInfo - Run tests after a Debug build for clearer asserts:
cmake --build vsbuild --config Debug --target runTests
ctest --test-dir vsbuild --config Debug --output-on-failure - Install compiled plugins into the preset install prefix (or the MO2 plugin dir if
MO2_PLUGIN_TARGET_DIRis set):
cmake --install vsbuild --config RelWithDebInfo - Package distributables (copies DLLs and translations into
package/):
cmake --build vsbuild --config RelWithDebInfo --target package
Coding Style & Naming Conventions
- C++17/20 with Qt6; follow WebKit
.clang-format: 2-space indents, aligned consecutive assignments, 120-column limit..editorconfigenforces 2-space indents for.cpp/.h/.uiand final newlines. - Classes use PascalCase (
FomodInstallerWindow), member functions and locals use lowerCamelCase; prefer descriptive names over abbreviations. - Keep UI strings in translation files; place shared helpers in
share/to avoid duplication.
Header File Patterns
- Use
#pragma oncefor include guards (preferred over#ifndefguards) - Member variables use
mprefix:mOrganizer,mFomodPath,mViewModel - Use
[[nodiscard]]attribute on getters and pure functions - Organize includes: local project includes first, then library includes, then Qt includes
Pragma Regions (.cpp files)
Use #pragma region to organize implementation files into logical sections. Common regions:
Initialization- Constructor, init(), setup functionsSettings- Configuration getters/settersHelpers- Private utility functionsViewModel Lifecycle- State managementTraversal Functions- Iteration logicInitializers- Object creationGroup Constraints/Plugin Constraints/Step Constraints- Validation logicNavigation/UI- User interaction handlersUtility- toString(), logging, misc
Example:
#pragma region Initialization
bool MyClass::init(IOrganizer* organizer) { ... }
#pragma endregion
#pragma region Settings
bool MyClass::shouldDoThing() const { ... }
#pragma endregion
Other Conventions
- Use
using namespace MOBase;andusing namespace std;at file scope in implementation files - Prefer
std::shared_ptrfor objects shared across components,std::unique_ptrfor owned objects - Use
finalon classes not intended for inheritance - Use modern C++ features:
std::ranges,std::optional, structured bindings,[[maybe_unused]]
Testing Guidelines
- GoogleTest is fetched in
tests/CMakeLists.txt; add new suites astests/test_<area>.cppor undertests/moduleconf/. - Favor small, fixture-backed tests that use existing XML samples; when adding data files, keep them minimal to reduce repo bloat.
- All new logic should have at least one failing test reproduced first, then fixed; ensure
ctest --output-on-failurepasses before PRs.
Commit & Pull Request Guidelines
- Commit messages in this repo are short, imperative, and single-sentence (e.g., “Clean up debug logs.”). Keep them under ~72 chars and scoped to one change.
- For PRs, include: what changed, why, how to verify (commands or screenshots for UI), linked issues if applicable, and any regression risks. Mark when CI/build artifacts were produced (via
packagetarget or GH Actions).