'use strict';
/**
* Keeps track of player quest progress
*
* @property {Player} player
* @property {Map} completedQuests
* @property {Map} activeQuests
*/
class QuestTracker {
/**
* @param {Player} player
* @param {Array} active
* @param {Array} completed
*/
constructor(player, active, completed) {
this.player = player;
this.activeQuests = new Map(active);
this.completedQuests = new Map(completed);
}
/**
* Proxy events to all active quests
* @param {string} event
* @param {...*} args
*/
emit(event, ...args) {
for (const [ qid, quest ] of this.activeQuests) {
quest.emit(event, ...args);
}
}
/**
* @param {EntityReference} qid
* @return {boolean}
*/
isActive(qid) {
return this.activeQuests.has(qid);
}
/**
* @param {EntityReference} qid
* @return {boolean}
*/
isComplete(qid) {
return this.completedQuests.has(qid);
}
get(qid) {
return this.activeQuests.get(qid);
}
/**
* @param {EntityReference} qid
*/
complete(qid) {
if (!this.isActive(qid)) {
throw new Error('Quest not started');
}
this.completedQuests.set(qid, {
started: this.activeQuests.get(qid).started,
completedAt: (new Date()).toJSON()
});
this.activeQuests.delete(qid);
}
/**
* @param {Quest} quest
*/
start(quest) {
const qid = quest.entityReference;
if (this.activeQuests.has(qid)) {
throw new Error('Quest already started');
}
quest.started = (new Date()).toJSON();
this.activeQuests.set(qid, quest);
quest.emit('start');
}
/**
* @param {GameState} state
* @param {object} questData Data pulled from the pfile
*/
hydrate(state) {
for (const [qid, data] of this.activeQuests) {
const quest = state.QuestFactory.create(state, qid, this.player, data.state);
quest.started = data.started;
quest.hydrate();
this.activeQuests.set(qid, quest);
}
}
/**
* @return {object}
*/
serialize() {
return {
completed: [...this.completedQuests],
active: [...this.activeQuests].map(([qid, quest]) => [qid, quest.serialize()]),
};
}
}
module.exports = QuestTracker;