This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Gecko is a modern cross-platform Fallout 2 map editor written in C++20. It uses Qt6 for the UI framework and SFML for 2D game rendering, supporting vanilla Fallout 2 and original Mapper file formats.
# Configure (from project root)
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
# Build editor
cmake --build build --target gecko --config Release
# Or with make (from build directory)
make -j4# Run all tests
ctest --test-dir build --output-on-failure
# Run the current test executables directly
./build/general_tests
./build/performance_testsThere is currently no separate qt_tests target or ctest label registration for test categories.
# Format all source files (uses clang-format with WebKit style)
./format.sh- gecko (executable): UI and editor functionality
- vault (static library): File format handling and I/O operations
src/format/: File format data structures (DAT, FRM, MAP, PRO, MSG, PAL)src/reader/: File format readers/parserssrc/writer/: File format writerssrc/ui/: Qt6 interface components (dialogs, panels, widgets)src/ui/rendering/: SFML rendering engine with viewport cullingsrc/editor/: Core editing logic (Object, HexagonGrid, Hex)src/selection/: Selection management systemsrc/util/: Utilities (Settings, Coordinates, helper modules)src/vfs/: Virtual file system for game archives
- Injected
resource::GameResourcesfacade DataFileSystem,ResourceRepository,FrmResolver, andTextureManager- DAT archive support via vfspp library
- URL: https://falloutmods.fandom.com/wiki/MAP_File_Format
- Description: Comprehensive documentation of Fallout 2 MAP file format
IMPORTANT: There are two different coordinate systems in Fallout 2 maps:
-
Tile Coordinates (Floor/Roof tiles):
- Grid size: 100×100 = 10,000 tiles per elevation
- Constant:
Map::TILES_PER_ELEVATION = 10000 - Used for: Floor tiles, roof tiles
-
Hex Coordinates (Objects, movement):
- Grid size: 200×200 = 40,000 hexes total
- Constants:
HexagonGrid::GRID_WIDTH = 200,HexagonGrid::GRID_HEIGHT = 200 - Total hexes:
GRID_WIDTH × GRID_HEIGHT = 40,000 - Used for: Object placement, character movement, hex-based interactions
- Never validate hex positions against
TILES_PER_ELEVATION- this is wrong! - Hex positions can be 0-39,999 (valid range)
- Tile positions can be 0-9,999 (valid range)
- Objects are positioned using hex coordinates (0-39,999)
- Use
worldPosToHexPosition()for hex coordinate conversion - Use
_hexgrid.getHexByPosition()to get hex data - Objects store
positionas hex index in MapObject
- Preview objects should use
setDirection(ObjectDirection(0))to show single frame - Apply semi-transparency:
setColor(sf::Color(255, 255, 255, 180)) - Objects without MapObject need null checks in
Object::setDirection()
- Ensure proper FRM loading using
resources.textures().get(frmPath) - Call
setDirection()aftersetSprite()to set correct texture rectangle - Check for null FRM before calling direction methods
- Always use correct ranges for validation:
- Hex positions:
< (HexagonGrid::GRID_WIDTH * HexagonGrid::GRID_HEIGHT) - Tile positions:
< Map::TILES_PER_ELEVATION
- Hex positions:
// Standard object creation pattern (existing objects)
auto object = std::make_shared<Object>(frm);
sf::Sprite sprite{ resources.textures().get(frmPath) };
object->setSprite(std::move(sprite));
object->setDirection(static_cast<ObjectDirection>(direction));
object->setHexPosition(hex);- Pass
resource::GameResourcesexplicitly through constructors - FRM files are stitched into sprite sheets by
TextureManager - Texture rectangles are set by
Object::setDirection()to show single frames
- Treat Fallout 2 CE and the shipped game data files as the source of truth for editor-visible values and IDs.
- Prefer loading values from runtime data such as
proto.msg,perk.msg,stat.msg, and related assets instead of duplicating label/value tables in UI code. - Preserve engine IDs exactly when reading or writing formats. UI widgets should map display labels to stored engine values; do not assume
QComboBoxindex is the serialized value unless the format explicitly works that way. - Do not add fallback label tables, placeholder enum names, or substitute values when required engine data is missing or incomplete. Surface the failure explicitly and fix the loader or data path.
- When a format detail is ambiguous, check
/Users/jansimek/Development/fallout2-ceand match the engine's parsing and naming behavior before adding editor-side constants or reinterpretations.
MapObject: Data structure for saving (shared_ptr in Map storage, unique_ptr only during parsing and for inventory children)Object: Visual representation with SFML sprite (shared_ptr)- Objects can exist without MapObject for preview purposes
- Qt drag events → SFMLWidget → EditorWidget
- Coordinate conversion: Qt screen → SFML window → World coordinates
- World coordinates → Hex position via
worldPosToHexPosition()
- Classes: PascalCase (
LoadingWidget) - Functions: camelCase (
loadMap) - Constants: SCREAMING_SNAKE (
TILES_PER_ELEVATION) - Private members:
_memberName - Slots: Use
onXxx()prefix for signal-connected slots (e.g.,onSearchTextChanged)
- C++20 required
- RAII and smart pointers throughout
std::filesystem::pathfor cross-platform file handling
All colors and styles are centralized in src/ui/theme/ThemeManager.h. Use theme constants instead of hardcoded values:
#include "../theme/ThemeManager.h"
// Colors - use ui::theme::colors::*
ui::theme::colors::PRIMARY // #4A90E2 - selection, focus
ui::theme::colors::PRIMARY_LIGHT // #E6F2FF - selected backgrounds
ui::theme::colors::SURFACE_DARK // #F0F0F0 - preview backgrounds
ui::theme::colors::ERROR // #D32F2F - error text
ui::theme::colors::WARNING // #F57C00 - warning text
// Spacing - use ui::theme::spacing::*
ui::theme::spacing::TIGHT // 4px - compact/nested layouts
ui::theme::spacing::NORMAL // 8px - standard widget spacing
ui::theme::spacing::LOOSE // 12px - dialog/group spacing
// Pre-built styles - use ui::theme::styles::*
setStyleSheet(ui::theme::styles::selectedWidget());
setStyleSheet(ui::theme::styles::previewArea());
setStyleSheet(ui::theme::styles::statusError());Use the established base class hierarchy for consistency:
| Base Class | Purpose | Key Methods |
|---|---|---|
BaseWidget |
All custom widgets | setupStandardVBoxLayout(), applySelectionStyle() |
BasePanel |
Palette/browser panels | createSearchControls(), createPaginationControls() |
BasePaletteWidget |
Grid items (tiles, objects) | Selection painting, drag handling |
Use constants from src/ui/dragdrop/MimeTypes.h:
#include "../dragdrop/MimeTypes.h"
// Setting MIME data
mimeData->setData(ui::mime::GECK_OBJECT, data);
// Checking MIME format
if (mimeData->hasFormat(ui::mime::GECK_OBJECT)) { ... }- Use theme spacing constants instead of hardcoded values
- Parent all widgets to ensure proper cleanup
- Use
BasePanel::createMainLayout()for consistent panel layouts - Stretch factors: Add stretch to push content (e.g.,
layout->addStretch())
- Use
on*prefix for slots connected to signals:onSearchTextChanged() - Use modern
connect()syntax with lambdas or method pointers - Emit signals with
Q_EMITfor clarity
- Copy
master.datandcritter.datfrom Fallout 2 toresources/ - Use Release builds for performance (Debug builds are slow for map loading)
- Run
./format.shbefore committing
GECK_USE_SYSTEM_LIBS=ON: Use system libraries when availableGECK_BUILD_TESTS=ON: Build tests (default)GECK_ENABLE_SANITIZERS=OFF: Enable sanitizers for debugging
Last updated: 2026-03-10 This file should be updated whenever significant architectural decisions or fixes are made.