Files
trail-into-darkness/CLAUDE.md
2026-04-19 12:46:44 +02:00

7.0 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Nox is a Unity 6 RPG game (product name "Nox", Windows build target Nox.exe). Party-based gameplay with Addressables for asset management, Newtonsoft JSON for serialization, URP 17.3.0 for rendering, and Unity Input System 1.18.0.

Build & Development

  • Unity version: 6.0.3 (C# 9.0, .NET Framework 4.7.1)
  • Build output: Builds/Nox.exe
  • No CI/CD pipeline — builds are done through Unity Editor
  • No test suite existscom.unity.test-framework is in manifest but unused
  • Scene authoring: Individual scenes can be played standalone via SceneReference component

Architecture

Dual-Layer State Management

Two layers of state drive the application:

  • Game States (IGameState): Application-level flow — SplashGameStateMainMenuGameStateGameModeGameState
    • Lifecycle: EnterGameState()Tick() / LateTick()ExitGameState()Dispose()
  • Play Modes (IPlayMode): Gameplay modes within GameMode — Adventure, Town, Rest, Combat, PauseMenu
    • Lifecycle: EnterPlayMode()Tick() / LateTick()ExitGameMode()Dispose()

GameModeGameState bridges these layers, managing play mode transitions and scene loading via Addressables. GameStateRunner (MonoBehaviour) drives the update loop and handles fade-in/fade-out transitions via ISceneTransition.

Boot Sequence

Boot.cs ([RuntimeInitializeOnLoadMethod]) → loads "Initializer" prefab via Addressables → EntryPoint.cs (MonoBehaviour) loads all config ScriptableObjects, creates game states, initializes platform subsystems and character systems → GameStateRunner begins ticking states.

In editor, Boot.cs checks BootMode preference (Full Boot, Scene Boot, Unity Default).

GameDataState

Central state container holding current GameState, PlayMode, ActiveParty, platformSelector, activeSessionId, and savedPartyPosition. State changes via ChangeGameState() and ChangePlayMode().

Character System

Factory-based architecture with ScriptableObject configuration:

DefaultCharacterSystemsFactory.Create()
├─ PerkFactory (PerkRegistry ScriptableObject)
├─ CharacterAttributesFactory (validates attributes)
├─ CharacterStatsFactory (derives stats from attributes)
├─ CharacterFactory (creates from templates or custom requests)
└─ PartyFactory (assembles: 1 protagonist + companions)
  • Data: EntityAttributes (might, reflex, knowledge, perception) → EntityStats (health, stamina, level, experience)
  • CharacterDefinition: ID, DisplayName, Attributes, Stats, Race, Class, Role (Protagonist/Companion), Perks, Modifiers
  • Config ScriptableObjects: CharacterBaseSettings, PerkRegistry, CharacterRegistry
  • Key interfaces: ICharacterSystems, ICharacterFactory, IPartyFactory, IPerkFactory

Persistence

GamePersistenceController + Jovian.SaveSystem with JSON serialization to Application.persistentDataPath. Save data model: NoxSavedDataSet (activePlayMode, partyDefinition, partyPosition, adventureData). Save slots managed by SaveSlotManager.

Platform Abstraction

IPlatform with DesktopPlatform and UnityEditorPlatform. Each initializes platform-specific IInput (DesktopInput/EditorInput using Unity InputSystem generated code).

Addressables Asset Keys

Assets loaded by string key: "Initializer", "AdventureMapPrefabs", "PauseMenuPrefabs", "AdventureSettings", "CharacterBaseSettings", "PerkRegistry", "CharacterRegistry", "BootstrapReferences".

Namespace Convention

Namespaces mirror folder structure: Nox.Core, Nox.Game, Nox.Input, Nox.Platform, Nox.Util.

Code Layout

Assets/Code/
├── Core/           # Boot, EntryPoint, GameStateRunner, IGameState, IPlayMode, GameDataState
├── GameState/
│   ├── Camera/     # CameraController, CameraSettings
│   ├── Entities/   # Character/Party/Perk factories and registries
│   ├── PlayModes/  # AdventurePlayMode, PauseMenuPlayMode, stubs for Town/Rest/Combat
│   └── UI/         # View implementations (PauseMenu, Adventure views)
├── Input/          # IInput abstraction, Desktop/Editor implementations
├── Platform/       # IPlatform, DesktopPlatform, UnityEditorPlatform
├── SplashMainMenuUI/
└── Util/           # BootMode editor utility

C# Style (from .editorconfig)

  • 4 spaces, LF line endings
  • var preferred (csharp_style_var_*: true:suggestion) — use var when type is apparent
  • Target-typed new when type is evident (CharacterDefinition c = new())
  • No space after keywords in control flow (if(, for(, not if ()
  • Opening braces on same line (csharp_new_line_before_open_brace = none)
  • else/catch/finally on new line after closing brace
  • Block-scoped namespaces (namespace Foo { ... })
  • Always use braces (csharp_prefer_braces = true)
  • Naming: PascalCase for types/methods/properties, camelCase for all fields (public and private), I prefix for interfaces
  • Expression-bodied: yes for properties/accessors/indexers/lambdas; no for constructors/methods/operators/local functions
  • No this. qualifier
  • Use language keywords over BCL types (int not Int32)

Patterns

  • Constructor-based dependency injection (no DI container)
  • ScriptableObject-based configuration loaded via Addressables
  • Factory pattern for character/party creation
  • Action delegates for UI event communication (e.g., menuGameStateData.startGameRequests += handler)
  • Mixed async patterns: both async Task and IEnumerator coroutines for async operations

Planning Docs Convention

Non-trivial features are planned in docs/plans/ as paired markdown files: a design doc and an implementation doc, both prefixed with the date. Examples: 2026-04-05-ingame-logging-design.md + 2026-04-05-ingame-logging-implementation.md, 2026-04-06-popup-system-design.md + 2026-04-06-popup-system-implementation.md. When starting a new feature, look here first for existing context, and follow the same pair-of-docs pattern for new work.

In-House Jovian Packages

Several packages under Packages/ are first-party code maintained alongside the game, not third-party dependencies. Before adding new capabilities, check whether one of these already provides what you need:

  • Jovian.SaveSystem — JSON persistence, used by GamePersistenceController
  • Jovian.Calendar — custom in-game calendar system
  • Jovian.InGameLogging — runtime logging surface
  • Jovian.EncounterSystem — data-driven encounter authoring, IEncounterKind polymorphic payloads, EncounterLink cross-table refs, QuestProgress gated progression + QuestLog. Designer browser at Jovian → Encounters → Encounter Browser.
  • Jovian.PopupSystem — popup/dialog UI
  • Jovian.ZoneSystem — zone/region management
  • Jovian.Logger — developer logging
  • Jovian.InspectorTools / JovianUtilities — editor and general utilities