Reason why I would not involve the character and controller in this is that it is unnecessary while using an ActorComponent instead makes the system portable.
You could store the row names of active quests from the datatable, or use a GUID per entry and scan all rows for a matching GUID which is more reliable. It really does not matter for performance. For a quest / objective to “be interested in the current event” they’d have to be UObjects in order to do so, which is heavier on performance and its complexity is not required.
Yes but instead of processing these events per quest object you could simply process it once on the ActorComponent, which is what I meant by looking up entries from the datatable from within the ActorComponent. It’s much simpler.
Logic:
QuestManager (ActorComponent):
- Holds a list of active quest GUIDs from the datatable.
- Binds to relevant events:
- DialogComponent::OnDialogFinished > QuestManager::UpdateQuestStatus
- InventoryComponent::OnInventoryChanged > QuestManager::UpdateQuestStatus
UpdateQuestStatus() {
// 1. Loop through datatable rows, every row holds a quest struct.
// 2. If GUID on the quest struct is stored as atctive quest on the ActorComponent, proceed.
// 3. Match quest completion requirements from struct against current status (inventory items / completed dialogs etc.)
// 4. If completion requirement is met, remove GUID from active quest and store the GUID as completed quest.
}