# BPC_JournalSystem — Journal System **Parent Class:** `ActorComponent` **Category:** Inventory **Target UE Version:** 5.5–5.7 **Build Phase:** 3 — Inventory ## 1. Overview `BPC_JournalSystem` manages the player journal — tracking discovered entries, quest notes, character bios, and lore entries. Provides query functions for UI display and narrative progression tracking. ## 2. Variables | Variable | Type | Description | |----------|------|-------------| | `JournalEntries` | `TArray` | All journal entries | | `EntryCategories` | `TArray` | Quest, Character, Lore, Notes, Tips | | `UnreadCount` | `int32` | Total unread entries | | `bAutoAddOnDiscovery` | `bool` | Auto-add entries on narrative flag | ## 3. Functions | Function | Description | |----------|-------------| | `AddJournalEntry` | Adds new entry | | `MarkAsRead` | Marks entry read | | `GetEntriesByCategory` | Returns filtered entries | | `HasEntry` | Checks if entry exists | | `GetUnreadCount` | Returns unread count | ## 4. Event Dispatchers | Dispatcher | Payload | Description | |------------|---------|-------------| | `OnJournalEntryAdded` | `S_JournalEntry Entry` | New entry discovered | | `OnJournalEntryRead` | `FGuid EntryID` | Entry marked read | ## 5. Dependencies | System | Relationship | |--------|--------------| | `BPC_NarrativeStateSystem` | Narrative-driven journal entries | | `WBP_JournalDocumentViewer` | UI display | ## 6. Reuse Notes - Journal entries are narrative-gated via gameplay tags --- ## 7. Manual Implementation Guide ### 7.1 Class Setup 1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_JournalSystem` 2. Add to Player Character 3. Define enum `E_JournalCategory`: Quest, Character, Lore, Notes, Tips 4. Define struct `S_JournalEntry`: `EntryID` (Guid), `EntryTag` (GameplayTag), `Title` (Text), `Body` (Text), `Category` (E_JournalCategory), `bIsRead` (Boolean), `Timestamp` (Float), `RequiredFlag` (GameplayTag), `SourceObjective` (GameplayTag) ### 7.2 Variable Initialization (BeginPlay) ``` Event BeginPlay ├─ Set JournalEntries = empty Array ├─ Set UnreadCount = 0 ├─ Set bAutoAddOnDiscovery = true ├─ Get Owner → Find Component by Class (BPC_NarrativeStateSystem) → Cache │ └─ Bind to OnNarrativeFlagSet → OnFlagSetHandler └─ Get Owner → Find Component by Class (BPC_ObjectiveSystem) → Cache └─ Bind to OnObjectiveCompleted → OnObjectiveCompleteHandler ``` ### 7.3 Function Implementations #### `AddJournalEntry(EntryTag: GameplayTag, Title: Text, Body: Text, Category: E_JournalCategory)` → `S_JournalEntry` ``` [Function: AddJournalEntry] Step 1: Check duplicate — ForEach JournalEntries: If Entry.EntryTag == EntryTag → return existing entry (no dupes) Step 2: Create S_JournalEntry: - EntryID = New Guid - EntryTag = input - Title = input - Body = input - Category = input - bIsRead = false - Timestamp = Get Game Time in Seconds Step 3: Add to JournalEntries array Step 4: Increment UnreadCount Step 5: Fire OnJournalEntryAdded(newEntry) Step 6: Return newEntry ``` **Nodes:** `New Guid`, `Make S_JournalEntry`, `Add to Array`, `Increment Int` #### `AddEntryFromDataAsset(JournalData: DA_JournalData)` → `S_JournalEntry` ``` [Function: AddEntryFromDataAsset] Step 1: Read fields from DA_JournalData Step 2: Call AddJournalEntry(Data.EntryTag, Data.Title, Data.Body, Data.Category) Step 3: If Data.RequiredFlag is valid AND bAutoAddOnDiscovery: Register listener on NarrativeStateSystem for that flag Step 4: Return entry ``` #### `MarkAsRead(EntryID: Guid)` → `void` ``` [Function: MarkAsRead] Step 1: ForEach JournalEntries (with Break): If Entry.EntryID == EntryID: If NOT Entry.bIsRead: Set bIsRead = true Decrement UnreadCount Fire OnJournalEntryRead(EntryID) Return ``` #### `GetEntriesByCategory(Category: E_JournalCategory)` → `Array` ``` [Function: GetEntriesByCategory] (Pure) Step 1: Results = empty Array Step 2: ForEach JournalEntries: If Entry.Category == Category → Add to Results Step 3: Return Results ``` #### `GetUnreadEntries()` → `Array` ``` [Function: GetUnreadEntries] (Pure) ForEach JournalEntries: If NOT Entry.bIsRead → Add to Results Return Results ``` #### `HasEntry(EntryTag: GameplayTag)` → `Boolean` ``` [Function: HasEntry] (Pure) ForEach JournalEntries: If Entry.EntryTag == EntryTag → Return true Return false ``` ### 7.4 Event Dispatcher Bindings | Bind to Dispatcher | Custom Event | Logic | |-------------------|-------------|-------| | `BPC_NarrativeStateSystem.OnNarrativeFlagSet(Flag)` | `OnFlagSetHandler` | Check if any journal entry has RequiredFlag == Flag → AddJournalEntry for that entry | | `BPC_ObjectiveSystem.OnObjectiveCompleted(ObjectiveTag)` | `OnObjectiveCompleteHandler` | Add journal entry summarizing completed objective | ### 7.5 Blueprint Build Checklist - [ ] Define enum `E_JournalCategory` and struct `S_JournalEntry` - [ ] Create BPC_JournalSystem, add to Player Character - [ ] Add variables: JournalEntries, EntryCategories, UnreadCount, bAutoAddOnDiscovery - [ ] Implement AddJournalEntry with duplicate check - [ ] Implement AddEntryFromDataAsset with DA_JournalData reading - [ ] Implement MarkAsRead with unread counter - [ ] Implement filtered query functions - [ ] Bind to NarrativeStateSystem and ObjectiveSystem for auto-adding - [ ] Test: progress story → journal entries appear → UI shows unread badge