Hi.
I have a small issue with the QuestList. It is not being saved. I have followed the gitlab commit but it doesn’t seem to work for me. It is the only thing that is not saved. As soon as I change scene it is removed. I think it might have to do with the old CaptureState in QuestStatus.cs but apparently if i try to remove it it gives me an error.
namespace RPG.Quests
{
public class QuestStatus
{
Quest quest;
List<string> completedObjectives = new List<string>();
[System.Serializable]
class QuestStatusRecord
{
public string questName;
public List<string> completedObjectives;
}
public QuestStatus(Quest quest)
{
this.quest = quest;
}
public QuestStatus(object objectState)
{
QuestStatusRecord state = objectState as QuestStatusRecord;
quest = Quest.GetByName(state.questName);
completedObjectives = state.completedObjectives;
}
public Quest GetQuest()
{
return quest;
}
public bool IsComplete()
{
foreach( var objective in quest.GetObjectives())
{
if(!completedObjectives.Contains(objective.reference))
{
return false;
}
}
return true;
}
public int GetCompletedCount()
{
return completedObjectives.Count;
}
public bool IsObjectiveComplete(string objective)
{
return completedObjectives.Contains(objective);
}
public void CompleteObjective(string objective)
{
if(quest.HasObjective(objective))
{
completedObjectives.Add(objective);
}
}
public object CaptureState()
{
QuestStatusRecord state = new QuestStatusRecord();
state.questName = quest.name;
state.completedObjectives = completedObjectives;
return state;
}
public QuestStatus(JToken objectState)
{
if (objectState is JObject state)
{
IDictionary<string, JToken> stateDict = state;
quest = Quest.GetByName(stateDict["questName"].ToObject<string>());
completedObjectives.Clear();
if (stateDict["completedObjectives"] is JArray completedState)
{
IList<JToken> completedStateArray = completedState;
foreach (JToken objective in completedStateArray)
{
completedObjectives.Add(objective.ToObject<string>());
}
}
}
}
public JToken CaptureAsJToken()
{
JObject state = new JObject();
IDictionary<string, JToken> stateDict = state;
stateDict["questName"] = quest.name;
JArray completedState = new JArray();
IList<JToken> completedStateArray = completedState;
foreach (string objective in completedObjectives)
{
completedStateArray.Add(JToken.FromObject(objective));
}
stateDict["completedObjectives"] = completedState;
return state;
}
}
}
namespace RPG.Quests
{
public class QuestList : MonoBehaviour, IPredicateEvaluator, IJsonSaveable
{
List<QuestStatus> statuses = new List<QuestStatus>();
public event Action onUpdate;
private void Update()
{
CompleteObjectivesByPredicates();
}
public void AddQuest(Quest quest)
{
if(HasQuest(quest)) return;
QuestStatus newStatus = new QuestStatus(quest);
statuses.Add(newStatus);
if (onUpdate != null)
{
onUpdate();
}
}
public void CompleteObjective(Quest quest, string objective)
{
QuestStatus status = GetQuestStatus(quest);
status.CompleteObjective(objective);
if(status.IsComplete())
{
GiveReward(quest);
}
if (onUpdate != null)
{
onUpdate();
}
}
public bool HasQuest(Quest quest)
{
return GetQuestStatus(quest) != null;
}
public IEnumerable<QuestStatus> GetStatuses()
{
return statuses;
}
private QuestStatus GetQuestStatus(Quest quest)
{
foreach (QuestStatus status in statuses)
{
if (status.GetQuest() == quest)
{
return status;
}
}
return null;
}
private void GiveReward(Quest quest)
{
foreach (var reward in quest.GetRewards())
{
bool success = GetComponent<Inventory>().AddToFirstEmptySlot(reward.item, reward.number);
if(!success)
{
GetComponent<ItemDropper>().DropItem(reward.item, reward.number);
}
}
}
private void CompleteObjectivesByPredicates()
{
foreach (QuestStatus status in statuses)
{
if (status.IsComplete()) continue;
Quest quest = status.GetQuest();
foreach (var objective in quest.GetObjectives())
{
if(status.IsObjectiveComplete(objective.reference)) continue;
if (!objective.usesCondition) continue;
if (objective.completionCondition.Check(GetComponents<IPredicateEvaluator>()))
{
CompleteObjective(quest, objective.reference);
}
}
}
}
public JToken CaptureAsJToken()
{
JArray state = new JArray();
IList<JToken> stateList = state;
foreach (QuestStatus status in statuses)
{
stateList.Add(status.CaptureAsJToken());
}
return state;
}
public void RestoreFromJToken(JToken state)
{
if (state is JArray stateArray)
{
statuses.Clear();
IList<JToken> stateList = stateArray;
foreach (JToken token in stateList)
{
statuses.Add(new QuestStatus(token));
}
}
}
public bool? Evaluate(string predicate, string[] parameters)
{
switch(predicate)
{
case "HasQuest":
return HasQuest(Quest.GetByName(parameters[0]));
case "CompletedQuest":
if(parameters[0]==null) return false;
Quest questToTest = Quest.GetByName(parameters[0]);
if(questToTest==null) return false;
if(!HasQuest(questToTest)) return false;
return GetQuestStatus(questToTest).IsComplete();
}
return null;
}
}
}