Some changes
This commit is contained in:
@@ -1,129 +1,19 @@
|
||||
# Dawn Godot — Claude Code Guide
|
||||
|
||||
## Project
|
||||
|
||||
Godot 4.4 RPG prototype, GDScript only. Viewport 480×270 (scaled 3× to 1440×810), GL Compatibility renderer.
|
||||
|
||||
---
|
||||
## Reference docs
|
||||
|
||||
## Code Style
|
||||
Detailed reference lives in [.claude/docs/](.claude/docs/):
|
||||
|
||||
### Naming
|
||||
- **camelCase** for variables and functions: `fighterMap`, `startBattle()`, `getFullParty()`
|
||||
- **PascalCase** for class names, enums, and enum values: `BattleFighter`, `FighterTeam`, `ALLY`
|
||||
- **SCREAMING_SNAKE_CASE** for constants and static data: `CUTSCENE_CONTINUE`, `ITEM_DATA`, `PARTY_JOHN`
|
||||
- **No** trailing underscores on private methods — use a leading underscore only for internal helpers that shouldn't be called externally: `_onConversationInteract()`, `_applyGravity()`
|
||||
- [Code Style](.claude/docs/code-style.md) — naming, formatting, general rules
|
||||
- [Architecture](.claude/docs/architecture.md) — singletons, scene graph, cutscene queue, data registry, `_init` pattern
|
||||
- [Systems](.claude/docs/systems.md) — battle, entities, items, UI conventions
|
||||
- [Dialogue](.claude/docs/dialogue.md) — DialogueManager integration, writing .dialogue files, DialogueAction
|
||||
- [Stubs](.claude/docs/stubs.md) — incomplete / placeholder systems to avoid relying on
|
||||
|
||||
### Formatting
|
||||
- 2-space indent (not 4, not tabs)
|
||||
- Type annotations on all variable declarations and function signatures: `var health:int`, `func damage(amount:int, crit:bool) -> void:`
|
||||
- No space between variable name and type: `var foo:int` not `var foo : int`
|
||||
- Blank lines between logical sections within a file; comment headers (`# Health`, `# Signals`) to label groups
|
||||
|
||||
### General Rules
|
||||
- `assert()` for invariants and preconditions — prefer it over silent failures
|
||||
- `params:Dictionary` pattern for multi-argument constructors/callables; access with `.get('key', default)` or `.has('key')` guards
|
||||
- `match` for enum dispatch; `if/elif` chains for non-exhaustive checks
|
||||
- `continue` / early `return` to reduce nesting rather than deep else-branches
|
||||
- Avoid long inline lambdas; extract named static functions where logic is non-trivial
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Singletons (Autoloads)
|
||||
All globally accessible by their handle. Never instantiate these — access via the global name.
|
||||
|
||||
| Handle | Role |
|
||||
|---|---|
|
||||
| `SCENE` | Current scene state; call `SCENE.setScene(SceneSingleton.SceneType.X)` to switch |
|
||||
| `TRANSITION` | Fade in/out; `TRANSITION.fade(FadeType, duration, color)` |
|
||||
| `BATTLE` | Battle state and fighter map |
|
||||
| `PARTY` | Party members (`PARTY.getFullParty()`) and `PARTY.BACKPACK` inventory |
|
||||
| `OVERWORLD` | Map switching with threaded loading |
|
||||
| `COOKING` | Cooking mini-game lifecycle |
|
||||
| `SAVE` | Persistence (stub) |
|
||||
| `QUEST` | Quest management (stub) |
|
||||
| `CUTSCENE` | Cutscene global (stub) |
|
||||
| `UI` | Root UI accessor — `UI.TEXTBOX`, `UI.DEBUG_MENU` |
|
||||
|
||||
### Scene Graph
|
||||
```
|
||||
RootScene (Node3D)
|
||||
└─ overworld / battle / cooking / initial ← one shown at a time
|
||||
RootUI (Control, always visible)
|
||||
└─ VNTextbox, DebugMenu
|
||||
```
|
||||
|
||||
`RootScene` listens to `SCENE.sceneChanged` and shows/hides the appropriate sub-tree.
|
||||
|
||||
### Cutscene / Event Queue
|
||||
`Cutscene` is the universal sequencing engine. It holds an `Array[Dictionary]` queue; each entry has a `"function": Callable` plus arbitrary data keys.
|
||||
|
||||
**Return codes from a callable:**
|
||||
- `Cutscene.CUTSCENE_CONTINUE` — advance to next item
|
||||
- `Cutscene.CUTSCENE_END` — stop the cutscene
|
||||
- An integer index — jump to that position
|
||||
|
||||
**Position constants when adding:**
|
||||
- `Cutscene.CUTSCENE_ADD_END` — append (default)
|
||||
- `Cutscene.CUTSCENE_ADD_NEXT` — insert immediately after current
|
||||
|
||||
**Callable pattern** — every action class exposes a pair:
|
||||
```gdscript
|
||||
# The actual callable (static, takes params:Dictionary, returns int)
|
||||
static func myCallable(params:Dictionary) -> int:
|
||||
...
|
||||
return Cutscene.CUTSCENE_CONTINUE
|
||||
|
||||
# Factory that builds the dictionary for addCallable()
|
||||
static func getMyCallable(arg) -> Dictionary:
|
||||
return { "function": myCallable, "myArg": arg }
|
||||
```
|
||||
|
||||
### Data Registry Pattern
|
||||
Static registries (Item, Recipe) follow this pattern:
|
||||
1. `enum Id { NULL, ... }` — typed identifier
|
||||
2. `static var DATA:Array = []` — indexed by Id value
|
||||
3. `static func define(params) -> Dictionary` — called at class load to populate `DATA`
|
||||
4. `static var FOO = define({...})` — registers the entry as a static var
|
||||
5. `static func get*(id) -> *` — typed accessors
|
||||
|
||||
### `_init(params:Dictionary)` Pattern
|
||||
Non-Node data classes (`BattleFighter`, `BattleDecision`, `ItemStack`, etc.) use a single `params` dictionary constructor with `.get('key', default)` for optional fields.
|
||||
|
||||
---
|
||||
|
||||
## System Conventions
|
||||
|
||||
### Battle
|
||||
- Fighters live in `BATTLE.fighterMap: Dictionary[BattlePosition, BattleFighter]`
|
||||
- `BattleFighter` is pure data (no Node); `BattleFighterScene` is the 3D visual
|
||||
- Battle flow is driven by `BattleCutsceneAction.playerDecisionCallable` which loops via `CUTSCENE_ADD_END`
|
||||
- New moves go in [battle/fighter/BattleMove.gd](battle/fighter/BattleMove.gd) as static presets; add corresponding `perform()` logic in [battle/action/BattleMove.gd](battle/action/BattleMove.gd)
|
||||
|
||||
### Entities (Overworld)
|
||||
- All interactable world objects extend `Entity` (CharacterBody3D)
|
||||
- Interaction type is set via `@export var interactType:InteractType`
|
||||
- Interaction routing lives in `EntityInteractableArea.onInteract()` — add new `InteractType` values there
|
||||
|
||||
### Items
|
||||
- Register new items in [item/Item.gd](item/Item.gd) — add to `Id` enum and call `itemDefine()`
|
||||
- Item ID order in the enum must match insertion order into `ITEM_DATA`
|
||||
|
||||
### UI
|
||||
- `UI.TEXTBOX.setTextAndWait(text)` — show dialogue and await player dismiss (use `await`)
|
||||
- Movement is blocked automatically when `UI.TEXTBOX` is visible (`EntityMovement._canMove()` checks this)
|
||||
- Menus extend `ClosableMenu` for open/close/toggle + `closed`/`opened` signals
|
||||
|
||||
---
|
||||
|
||||
## What's Incomplete / Stub
|
||||
- `Save.gd` — no actual serialization yet
|
||||
- `Quest.gd` — empty singleton
|
||||
- `CutsceneSingleton.gd` — minimal stub
|
||||
- `BattleFighter.getAIDecision()` — always returns `null`
|
||||
- `BattleDecision.execute()` — stub
|
||||
- `BattleItem.perform()` — stub
|
||||
- `CookingScene.tscn` — placeholder UI only
|
||||
- `Pause.gd` — commented-out logic
|
||||
@.claude/docs/code-style.md
|
||||
@.claude/docs/architecture.md
|
||||
@.claude/docs/systems.md
|
||||
@.claude/docs/dialogue.md
|
||||
@.claude/docs/stubs.md
|
||||
|
||||
Reference in New Issue
Block a user