Quest / Mission System?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Brandon Lamb
:warning: Old Version Published before Godot 3 was released.

Does anyone have any links/articles/blogs/videos to share, or tips themselves on how to approach the development of a mission/quest system?

Google did not help much. A few unity asset library things, one Java library, and then articles on the design philosophies but no actual coding tutorials.

I’m curious on possible class / code structure ideas, and the intent would be to have something re-usable and not hard-coded, but also not totally over-engineered.

This is an overly broad question, which is probably why you had trouble finding information. There are a great many ways to define “mission” or “quest” and many possible solutions for each one. For example, it could be as simple as a list of quest IDs and flags (eligible, in progress, completed), etc., or it could be a complex, scripted web of scenes and events.

I suggest you first sketch out the design (on paper) for what you’re envisioning. Many times this is all it takes to then see a good data structure/process for implementing it. At that point you can ask more specific questions about implementation strategies.

kidscancode | 2017-08-14 02:11

I have to disagree that this is an overly broad question. Below are notes I took from a great article, but I didn’t save the URL (I’ll have to go dig through my bookmarks to see if I bookmarked).

Quest/mission systems can typically fall into a handful of types:

  • Kill
  • Gather
  • Escort
  • FedX/Deliver
  • Defend
  • Profit
  • Activate
  • Search

These then may typically fall into a handful of patterns:

  • Arrowhead
  • Side stub
  • Continuous side quests
  • Deadline
  • Deja-vu quests
  • Delayed impact
  • One of many
  • Hidden quests
  • Moral dilemna
  • Side quests
  • Tournament
  • Vehicle missions

You then may have either a linear quest hub design or open-world model.

Now given above, you can probably forget about most of that when my question is around basic design. A quest/mission probably has some basic properties:

  • Quest ID
  • Name
  • Description/text
  • Status (started, finished, failed)
  • Rewards (what does the player get for completing, could be an item, experience, etc)
  • Requirements (must be level 3, must have an item, etc)
  • Goals/objectives (kill 3 trolls, craft 3 bread, etc)

I happened across a C# gist on github which I then took and started an initial take at a quest system for Godot:

GitHub - godot-addons/godot-quest-system: Godot Engine (v3.0) Quest System

My original question was hoping that someone who has actually created a quest/mission system before would have some tips on where to start.

Things I’ve discovered so far is that there probably needs to be some kind of persistence. This could be purely in-memory, persisted to a file (could be json, xml, other), or some kind of database interaction (sqlite?).

I then happened upon a godot sqlite addon (for both v2 and v3-alpha via GDNative) but it did not work for me. Probably missing a bunch of install steps.

I’m trying to take a data-driven/DDD approach so you will notice that the repo above is pure code, where my intent would be to drive some UIs with complete separation of concerns.

Another thing that for my game specifically I may (or may not) want is designed vs procedurally generated quests/missions.

I’ll probably update this post later when I have learned more.

Brandon Lamb | 2017-08-14 13:36

Well, I guess we just have a very different definition of “broad.” :stuck_out_tongue: . Your response lists a huge variety of possible architectures. Are you looking to build a generic quest system that can be used as a plugin for any game? That’s a very different question than how to make a system for your particular needs in a single game.

I just think you’re going to have trouble getting useful answers here. This QA forum is better suited for direct answers to specific questions, so you may not get many responses.

kidscancode | 2017-08-14 15:35

did you ever find a good tutorial or anything to answer your question?

tmit30 | 2020-09-27 19:40

:bust_in_silhouette: Reply From: davidoc

I worked with Gamecore3D and it had a basic quest system, I had to unearth that code to review how it was implemented, I have not implemented it in Godot but I’d do something like this (emulating what Gamecore did):

a) Use a singleton to manage quests (QuestManager)
-QuestManager has a quest array (Dictionary?) where you add quests to this dictionary
b) Create a Quest Class with this functions: IsMissionSuccessful, RunMission,CleanUpMission
-RunMission is called by QuestManager when you add it to the dictionary (you should use yield)
-RunMission sets up the mission (load NPCs, treasure,etc), enters a loop waiting until conditions are met and sets if mission is successful or not
-CleanUpMission removes quest elements and is called by QuestManager when RunMission ends
-IsMissionSuccessful just returns the value you set within RunMission

As I said it is a basic system, but you could build over it adding persistance, report mission progress, left time, etc.

This is the code I had for a simple “Move to the point” mission when game started:


// Initial mission, just get to the marker
Object @destinationMarker;

void RunMission()
{
	//--------------------------------
	// setup

	Viewport@ viewport = GetGameManager().GetViewport( "Main");

	//--------------------------------
	// intro cinematic

	//LoadCinematicScript( "../cinematics/start_intro.gsl");
	//WaitForCinematicToEnd();

	//--------------------------------
	// mission gameplay

	@destinationMarker = GetGameManager().GetWorld().GetObject( "StartMarker");
	destinationMarker.Show();
	destinationMarker.SetMapMarkerVisible( true);
	destinationMarker.SetControllerVariable( "Reset", true);

	GetGameManager().SetTextAlignment( "Center", "Subtitle");
	GetGameManager().ShowTextPlain( "Llega al marcador para iniciar la primera mision.", 3.5);
	Delay(4);
	GetGameManager().ShowTextPlain( "El objetivo aparece como un circulo amarillo en el mini-mapa.", 3);

	while (true){
		// check if we're at the destination
		if (destinationMarker.GetControllerVariableBool( "Activated"))
			break;
		Delay( 0.01);
	}

	destinationMarker.Hide();
	destinationMarker.SetMapMarkerVisible( false);
	
	SetMissionSuccessful( true);
}

void CleanUpMission(){
	if (destinationMarker != null){
		destinationMarker.Hide();
		destinationMarker.SetMapMarkerVisible( false);
	}
}