I’m making some quests in my game. The quest actor is very simple. It doesn’t do anything. It’s mostly a holder for a bunch of variables. I made it a placeable actor so that I could make archetypes from it to represent all the different quests you can do.
One kind of quest tells you to go talk to someone else. So I’d like my quest class to have something like this:
var() Pawn TalkToThisPawnToCompleteTheQuest;
So I made the quest archetype and saved it in a package. You talk to one NPC pawn, get the quest, and to complete the quest you go talk to a different NPC pawn. The problem is that the quest archetype saved in a package is not allowed to reference an actor in the game world.
Warning: Illegal text reference to a private object in external package (SRVPawnNPC Test_StreamingQuest_01.TheWorld:PersistentLevel.SRVPawnNPC_0) from referencer (SRVQuest Test.Quests.SRV_TestQuest_01). Import failed...
Then I thought maybe I can’t use archetypes in content packages for my quests. Maybe my quest actors have to exist in the game world, and then they can reference the other actors in the game world.
That would work, except that I can’t reference actors in a different streaming level. Same problem.
Warning: Illegal text reference to a private object in external package (SRVPawnNPC Test_StreamingQuest_01.TheWorld:PersistentLevel.SRVPawnNPC_0) from referencer (SRVQuest Test_StreamingQuestPersistent.TheWorld:PersistentLevel.SRVQuest_0). Import failed...
What do you think would be the best way to have an NPC pawn in one level give you a quest that tells you to talk to an NPC pawn in a different level?
For now, I think I have to put all of my NPCs in the persistent level, and all of my quests have to be actors in the persistent level so that the quests can have references to the NPCs. For the NPCs that should be in streaming levels, I’ll have to turn their physics on and off when that level loads/unloads so that the NPCs don’t fall into the void.
I would use the GameMode to handle all these tasks. After init and level load it would collect all your quest objects and manage them.
GameModes should be the man object to gandle Game logic . The level should only show where things should be and not how they work.
OK, so do you know how I can save my quest archetypes in a package separate from the level and still have them refer to the desired pawn in the game world?
There are several possibilities:
- Give the character a name variable and search for it
- Use tags on the actors (this would be the most common one, I suppose because it has built in engine support)
- Implement an interface which supports the functionality and loop over all actors with this interface
- Let the character register at the GameMode on its own after initialization
These are ones which I think of at first clance. There might be some further possibilities.
I use the actor tag to search it in the quests. If that task is not used every frame during gameplay, but one time for example in a quest step, I think is the best solution.
Thank you both for the suggestions. But in each of your suggestions, the quest’s reference to the pawn will be none if the pawn’s streaming level isn’t loaded, right?
So I have this menu that shows which quests an NPC is offering:
The only things I manually type for that are the quest name (Defeat Turkeys) and the little flavor text blurb (These pesky turkeys have invaded my farm…). Everything else gets placed there programmatically based on the quest’s parameters.
The problem with any approach I’ve tried (and I think also, with the approaches you’ve suggested) is that
TalkToThisPawnToCompleteTheQuest variable will be
none if the level containing TalkToThisPawnToCompleteTheQuest isn’t loaded.
So let’s say this farmer has a quest that tells you to go to a different town (in a different streaming level that isn’t loaded) to talk to a different NPC and let’s say his name is “John.” The line that reads “Then return to Farmer” in the screenshot in that case should be “Then speak to John.” But unless John’s level is loaded, the reference to John is none, and the quest parser doesn’t know the name of the NPC you’re supposed to talk to.
I could type the quest instructions manually for every quest instead of letting the parser create the quest instructions for me. That would solve the issue. I could also create a brush that I could use to build the text, but then I would have to localize that text for every language, instead of, once again, letting the parser (which I would only have to localize once) build the text for me.
I don’t think there’s any way around keeping the pawns and the quests in the same level.
Now I understand. No you shouldn’t load the Characters when you are in a different level, this is a waste of performance especially when you have many quests etc.
You have to hold your quest information in a separate “module” ( for example an ActorComponent in your GameMode). If you want uo connect the quest with a character don’t use its real reference but an ID or something similar, so you don’t have to load the character at all.