# U-Tad UI Project **English** | **[Leer en EspaƱol](README-es.md)** --- ## Skill Tree System Implementation ### Overview A complete skill tree system with node-based progression, prerequisite validation, visual connection lines, and data-driven configuration. ![Overview 1](Docs/Images/Overview_1.png) --- ## 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 ![Decision Blueprint 1](Docs/Images/DecisionBlueprint_1.png) --- ## 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. ![Data Layer 1](Docs/Images/DataLayer_1.png) ### 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.

Lines 1 Lines 1

### 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