Skip to content

Instantly share code, notes, and snippets.

@grofit
Last active June 25, 2023 11:31
Show Gist options
  • Save grofit/651efe441472da4e29fa to your computer and use it in GitHub Desktop.
Save grofit/651efe441472da4e29fa to your computer and use it in GitHub Desktop.
Quick RPG Quest System Example
So the general idea here is that the quest encapsulates (through composition) all the data requirements of a quest. This means you could easily create a quest without any engine specific knowledge and in an external tool or in any general format, like json, xml, csv etc.
Now this is only half the picture as you need some other classes to process this class, such as something like:
public class RequirementProcessor
{
private CharacterRepository _characterRepository;
private TriggerRepository _triggerRepository;
private FactionRepository _factionRepository;
public bool AreRequirementsMet(Quest quest) {
// check each requirement type
// go read relevant repo to verify
// return true or false
}
}
So this allows you to test and encapsulate your logic without it being engine specific. it also lets you consume this logic wherever you want and use IoC and DI if available.
{
"id": 1,
"name": "Fetch Some Bread",
"description": "Some guy wants some bread, go to the town and fetch him some."
"requirements": [],
"rewards": [
{ "type": 1, "rewardInt": 1000 }, // 100 xp
{ "type": 6, "rewardInt": 10 } // 10 gold
],
"objectives": [
{ "type": 1, "objectiveInt": 102 } // item number 102 held (bread)
]
}
public class Objective
{
public ObjectiveType Type {get;set;}
public int ObjectiveInt {get;set;}
public float ObjectiveFloat {get;set;}
public Vector3 ObjectiveVector {get;set;}
// could possibly use Dictionary instead
}
public enum ObjectiveType
{
Unknown = 0,
ItemsHeld = 1,
Gold = 2,
EnemiesKilled = 3,
DestinationReached = 4,
TriggerEnabled = 5,
// etc
}
public class Quest
{
public int Id {get; set;}
public string Name {get;set;}
public string Description {get;set;}
public IList<Reward> Rewards {get; private set; }
public IList<Requirement> Requirements {get; private set; }
public IList<Objective> Objectives {get; private set; }
public event QuestEventHandler OnStarted;
public event QuestEventHandler OnProgress;
public event QuestEventHandler OnObjectivesComplete;
public event QuestEventHandler OnFinished;
}
public class Requirement
{
public RequirementType Type { get; set; }
public float RequiredNumber { get; set; }
public string RequiredString { get; set; }
}
public enum RequirementType
{
Unknown = 0,
Level = 1,
Class = 2,
Race = 3,
FactionScore = 4,
TriggerActive = 5,
TriggerDeactive = 6,
ItemHeld = 7
// etc
}
public class Reward
{
public RewardType Type { get; set; }
public float RewardFloat { get; set; }
public int RewardInt { get; set; }
// again maybe a dictionary is better fit.
}
public enum RewardType
{
Unknown = 0,
Experience = 1,
Item = 2,
TriggerActivated = 3,
TriggerDeactivated = 4,
FactionScore = 5,
Gold = 6
// etc
}
@jonlepage
Copy link

hum curious , and how you work with update?
You create a pool and check all quests in pool each frame ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment