diff --git a/README.md b/README.md index 75c50aa..967fed6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,126 @@ # U-Tad UI Project +## Skill Tree System Implementation + +### Overview +A complete skill tree system with node-based progression, prerequisite validation, visual connection lines, and data-driven configuration. + +--- + +## Architecture: Blueprint Decision + +### Blueprint Implementation +**Components:** `WBP_SkillTree`, `WBP_SkillNode`, `WBP_SkillNodeTooltip` + +**Reasoning:** +- **Iteration speed**: UI layout and styling require rapid visual iteration +- **Designer-friendly**: Artists/designers can modify UI without C++ knowledge + +--- + +## Core Systems + +### 1. Data Layer (`SkillTreeTypes.h`) +**Structures:** +- `FSkillNodeData`: Skill definition row for skill data table (name, cost, prerequisites, effects, starting flag) +- `FSkillNodeRuntime`: Runtime state wrapper +- `ESkillNodeState`: State enum (Locked, Available, Selected, Purchased) + +**Decision**: Data Table-driven design allows non-programmers to configure skills without recompiling. + +### 2. Logic Layer (`SkillTreeComponent`) +**Responsibilities:** +- Skill tree initialization from DataTable +- State management (prerequisites, affordability checks) +- Selection validation and purchase confirmation +- Starting skills auto-purchase +- Skill point management +- Effect application hooks + +**Key Features:** +- **Purchase order sorting**: Ensures prerequisites are purchased before dependents +- **Cascade deselection**: Removing a prerequisite deselects dependent skills +- **Starting skills**: Marked in DataTable, auto-purchased at init, preserved on reset +- **Stat aggregation**: Provides `GetTotal[Stat]Bonus()` functions to sum all purchased skills' bonuses + +### 3. Stats Integration Layer (`CharacterStatsComponent`) +**Responsibilities:** +- Automatic stat calculation from purchased skills +- Character stat management (Health, Damage, Speed) +- Real-time updates when skills are purchased +- Movement speed integration + +**How it works:** +- Finds SkillTreeComponent on same actor at BeginPlay +- Listens to `OnSkillPurchased` event +- Iterates all purchased skills, sums flat + percentage bonuses +- Applies formula: `FinalStat = Base + FlatBonus + (Base * PercentBonus / 100)` +- Auto-updates CharacterMovementComponent speed +- Broadcasts stat change events for UI updates + +**Decision**: Separate stats component keeps concerns separated - SkillTreeComponent handles progression, CharacterStatsComponent handles stat application. Makes both reusable independently. + +### 4. Visualization Layer (`SkillTreeConnectionsWidget`) +**Responsibilities:** +- Automatic line drawing between prerequisite nodes (You only need to place nodes in the UI!) +- Dynamic line coloring based on skill states +- Event-driven refresh on state changes + +**Technical Approach:** +- **Generic search**: Works with any widget hierarchy so designers/artist are not limited when creating the skill tree widget (Canvas, Overlay, Grid) +- **NativePaint override**: Direct Slate rendering for performance +- **Delegate binding**: Auto-refreshes when skills change state + +**Decision**: Single self-contained widget eliminates manual line management and Blueprint complexity. + +### 5. UI Layer (Blueprints) +**WBP_SkillNode & WBP_SkillNodeTooltip:** +- Displays skill icon, state, cost +- Handles click events (select/deselect) +- Stores SkillID for runtime lookup +- Custom tooltip support to display skill details +- Real time state updates via event binding allows real-time visual feedback + +**WBP_SkillTree:** +- Contains manually-placed skill nodes +- References SkillTreeComponent +- Hosts SkillTreeConnectionsWidget which draws lines between nodes automatically +- Binds to component events for UI updates + +**Decision**: Manual node placement allows custom layouts (linear, radial, branching) per designer preference. + +--- + +## Key Design Decisions + +### 1. Skill prerequisites in DataTable +**Alternative**: Hard-coded in C++ or DataAssets references +**Chosen**: DataTable array +**Reason**: Designers can modify skill dependencies without programmer intervention and without recompiling + +### 2. Component vs Subsystem +**Alternative**: Game Instance Subsystem +**Chosen**: Actor Component +**Reason**: Supports multiple skill trees per player (e.g., combat tree, crafting tree) and easier save/load integration + +### 3. Single Connections Widget +**Alternative**: Individual line widgets per connection with manual management +**Chosen**: One widget draws all lines automatically +**Reason**: Eliminates array management, better performance, automatic coordinate handling + +### 4. Separate Stats Component +**Alternative**: Apply stats directly in SkillTreeComponent +**Chosen**: Separate CharacterStatsComponent +**Reason**: Separation of concerns - SkillTreeComponent is reusable for any progression system, CharacterStatsComponent specifically handles character stats. Allows skill trees without stat bonuses, or stats without skill trees. + +--- + +## Technical Highlights + +- **Event-driven architecture**: Component broadcasts state changes, UI responds automatically +- **State machine validation**: Prevents invalid transitions (e.g., can't select locked skills) +- **Automatic stat application**: CharacterStatsComponent listens to skill purchases, recalculates stats, applies to character +- **Geometry-aware rendering**: Lines adapt to any widget positioning system +- **Data-driven configuration**: Zero code changes and no need to compile for new skills or tree layouts +- **Reset functionality**: Refunds non-starting skills, maintains starting points +- **Modular design**: Skill progression, stats, and visualization are independent