# DartGame A 3D darts game where the core loop is **dragging modifiers onto board sectors** to create compounding scoring interactions. Balatro's joker system, applied to a dartboard. Built in **Godot 4.7**. Modding is a first-class concern, not an afterthought — our own content ships through the same loader community mods will use. --- ## ⚠️ Install `git-lfs` BEFORE you clone Clone without it and you'll get **130-byte text pointers** where your textures and models should be. Godot will throw import errors that look completely baffling and you will lose an hour. **NixOS** — Home Manager (also writes the LFS filter config, so a fresh machine is correct with no imperative step): ```nix programs.git = { enable = true; lfs.enable = true; }; ``` Or system-wide: ```nix environment.systemPackages = with pkgs; [ git git-lfs ]; ``` **Debian/Ubuntu** — `sudo apt install git-lfs` **macOS** — `brew install git-lfs` Then, once per machine: ```bash git lfs install ``` --- ## Clone ```bash git clone ssh://git@gitea.lilpenn.org:30009/ced/DartGame.git cd DartGame ``` > **Note the `git@`.** Without it, SSH tries to log in as your local username and you get > `Permission denied (publickey)`. Gitea's SSH user is always `git`. ### Verify LFS worked ```bash file game/core/board/dartboard.glb ``` **Want:** `glTF binary model, version 2, length 3302888 bytes` **Bad:** `ASCII text` ← that's an unfetched LFS pointer. Stop and fix it before opening Godot. --- ## Setup ```bash # GDScript formatter + linter nix-shell -p gdtoolkit_4 # or: pipx install "gdtoolkit==4.*" # Pre-commit hooks pre-commit install ``` Then point Godot 4 at `game/project.godot`. --- ## Where things live | | Nextcloud | This repo | |---|---|---| | `.blend`, `.kra`, `.psd` | ✅ | ❌ **never** | | `.glb`, `.png` (exported) | ❌ | ✅ (LFS) | | `.res` (collision shapes) | ❌ | ✅ (LFS) | | Code, scenes, `.tres` | ❌ | ✅ | | Moodboards, references | ✅ | ❌ | | **Documentation** | ✅ | ❌ | Source files live in the **company Nextcloud share**, not here. They churn constantly, never merge, and 99% of their revisions have no corresponding code change — they'd bloat LFS history forever, on every clone. Exported artifacts **do** live here, because they must version in lockstep with the code that references them. If a UV layout changes and a script needs updating, those belong in one commit. [`SOURCES.md`](SOURCES.md) maps each repo artifact back to its Nextcloud source. --- ## Layout ``` game/ ├── core/ ← THE ENGINE. Contains zero game content. Ever. │ ├── board/ dartboard scene, mesh, 21-slot logic, trimesh collision │ ├── dart/ dart scene, drag/throw/flight physics │ ├── modding/ mod registry, modifier base class │ └── ui/ drop catcher, modifier tray, sector swatch ├── content/official/ ← OUR CONTENT, loaded as a mod like any other │ ├── mod.json │ ├── skins/ bulls/ · sectors/ · flat_tire/ │ └── modifiers/ (empty — Phase 5) └── scenes/ main.tscn, camera_3d.gd ``` ### The two rules **1. Nothing in `core/` knows about any specific content.** About to write `if modifier.id == "mjolnir"` in `core/`? Stop — you need a new primitive. **2. `content/official/` must be deletable.** Delete it, and the game boots to an empty state without crashing. That's the proof the mod pipeline is real. If it can't, we don't have a mod system — we have a plugin folder. --- ## The board is 21 slots `dartboard.glb` exports 21 material slots: `sector_1` … `sector_20`, plus `bulls`. Each sector is its own material, so it can be skinned and modified independently. Hit detection reads the **mesh face index** from the raycast and maps it to the material name — *not* an angle. That's what lets a modifier rotate or remap the board and still score correctly. Full detail in the docs. --- ## Docs Full documentation is an Obsidian vault at `Nextcloud/DartGame/documentation/`. **Start with `Build Plan`.** Then `Conventions` before your first commit. | Note | | |---|---| | **Build Plan** | What we're building. Eight phases, current status. | | **Conventions** | Naming, git workflow, linting. **Read before your first commit.** | | **Architecture** | How the engine works and why. | | **Godot Gotchas** | Every trap that cost us time. Read it. | | **Modding** | The mod format and public API. | | **Asset Pipeline** | Nextcloud ↔ repo handoff, Blender export settings. | | **File Tree** | Full directory reference. | --- ## Contributing **Branches:** `feat/`, `fix/`, `chore/` off `main`. `main` is protected and always runnable. **Commits:** Conventional Commits. ``` feat(modding): add ModRegistry namespaced lookup fix(board): face-to-slot map missed the last surface ``` **Before you open a PR:** - [ ] `gdformat --check game/` passes - [ ] `gdlint game/` passes - [ ] Nothing in `core/` references a specific content ID - [ ] If an asset changed: source updated in Nextcloud, `SOURCES.md` current - [ ] `git lfs status` shows binaries as LFS ### ⚠️ Moving files **Commit first.** Godot's refactoring is fragile. Move files from **inside the Godot editor's FileSystem dock**, never your file manager, so references get fixed up. If things break after a move or branch switch: ```bash rm -rf game/.godot/ ``` then Project → Reload Current Project. Worse than that? `git restore .` — which only works if you committed first. --- ## Status **Pre-alpha.** Phase 0 (repo hygiene) complete. Phase 1 (skeleton) in progress — board and dart scenes exist with collision; the throw mechanic is still being tuned. See `Build Plan` in the docs vault.