RPG elements in a home-brew game engine aren't difficult, but are hilariously complex to code. Look at the number of bugs in Skyrim, which still exist years after release.
Each npc entity has it's own dialogue when the player interacts with it, and that dialogue will very likely change when quests are completed, abandoned or failed. It may even change depending on some kind of reputation like mechanic.
First, map out your interaction tree on paper in a logical way:
- Each entity should have N dialogues (which may be cut scenes).
- Each dialogue should have M conditions which need to be met (M can
Functionally, each entity should have a collection of dialogues/scripted cut-scenes, and a script of some kind which will select the dialogue out of the collection depending on some data that the player entity contains. This will likely involve writing a scripting system. I recommend using LUA and luabridge. There are some really nice tutorials on this, so I won't cover it here. A very simplistic example of such a LUA script would follow:
function getDialogue(entity, player)
local progress = player.getQuestProgress()
local questProgress = progress.getProgress(entity.getQuestID())
In this example, each quest has a unique id, and each dialogue is unique within each npc.
The "progress" object is just a collection of integers, which store data on each quest in the game (0, for not default, 1 for in progress, 2 for complete).
If quest progress is 0, then the entity will offer the quest to the player when interacted with.
If 1, then the quest is in progress, and so a sort of "How are you progressing?" sort of dialogue should be used.
If 2, then a generic "Thanks for your help!" type dialogue.
In the case of cut scenes, this is more complex, but the basic idea is to shut off player controls (except maybe skip cut-scene), and then allow the script to control the camera and dialogue/animation.
To do this, you will have to tie up pretty much all your game engine and entity functions to your scripting engine, allowing C++ functions to be called from LUA. This will take some time, but is worth it in the end, as it allows you to test your scripts without recompiling your source.
Once you have an adequate amount of control of your engine from scripts, you will be surprised just how much control over your game you have.