All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.blastedstudios.gdxworld.world.quest.GDXQuestManager Maven / Gradle / Ivy

The newest version!
package com.blastedstudios.gdxworld.world.quest;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.blastedstudios.gdxworld.util.Log;
import com.blastedstudios.gdxworld.util.Properties;
import com.blastedstudios.gdxworld.world.GDXLevel;
import com.blastedstudios.gdxworld.world.quest.QuestStatus.CompletionEnum;
import com.blastedstudios.gdxworld.world.quest.manifestation.IQuestManifestationExecutor;
import com.blastedstudios.gdxworld.world.quest.trigger.AbstractQuestTrigger;
import com.blastedstudios.gdxworld.world.quest.trigger.IQuestTriggerInformationProvider;

/**
 * Manager for quests for each client/player. This will determine what quests
 * are available, if they are to be triggered, and will trigger the quest.
 * 
 * Intention is to go in higher level manager and tick every frame so that
 * progress may occur seamlessly. Should be the main visible thing to
 * quest programmer.
 */
public class GDXQuestManager implements Serializable{
	private static final long serialVersionUID = 1L;
	private transient IQuestTriggerInformationProvider provider;
	private transient IQuestManifestationExecutor executor;
	private transient GDXLevel currentLevel;
	private transient Map currentLevelQuestMap;
	private Map> levelQuestStatusMap = new HashMap<>();

	public void initialize(IQuestTriggerInformationProvider provider,
			IQuestManifestationExecutor executor){
		this.provider = provider;
		this.executor = executor;
	}

	public void setCurrentLevel(GDXLevel currentLevel) {
		this.currentLevel = currentLevel;
		Log.log("GDXQuestManager.setCurrentLevel", "set level: " + currentLevel);
		if(!levelQuestStatusMap.containsKey(currentLevel.getName()) || 
				!Properties.getBool("quest.status.restore", false)){
			List statuses = new LinkedList<>();
			for(GDXQuest quest : currentLevel.getQuests())
				statuses.add(new QuestStatus(currentLevel.getName(), quest.getName()));
			Collections.sort(statuses, new QuestStatus.CompletionComparator());
			levelQuestStatusMap.put(currentLevel.getName(), statuses);
		}
		currentLevelQuestMap = new HashMap<>();
		for(GDXQuest quest : currentLevel.getQuests()){
			GDXQuest dupe = (GDXQuest) quest.clone();
			dupe.initialize(provider, executor);
			currentLevelQuestMap.put(quest.getName(), dupe);
		}
	}
	
	public void tick(float dt){
		if(levelQuestStatusMap == null || currentLevel == null){
			Log.debug("GDXQuestManager.tick", "levelQuestStatusMap or currentLevel null, aborting");
			return;
		}
		List statuses = levelQuestStatusMap.get(currentLevel.getName());
		if(statuses == null){
			Log.error("GDXQuestManager.tick", "levelQuestStatusMap does not contain level: " + currentLevel);
			return;
		}
		boolean statusChanged = false;	//can't sort while looping through map
		for(QuestStatus status : statuses){
			GDXQuest quest = currentLevelQuestMap.get(status.questName);
			if(status.getCompleted() == CompletionEnum.NOT_STARTED || quest.isRepeatable()){
				if(isActive(quest)){
					boolean activate = true;
					for(AbstractQuestTrigger trigger : quest.getTriggers())
						activate &= trigger.activate(dt);
					if(activate){
						status.setCompleted(quest.getManifestation().execute(dt));
						completeQuest(quest, status);
						statusChanged = true;
						Log.log("GDXQuestManager.tick", "Quest manifested: " + quest);
					}
				}
			}else if(status.getCompleted() == CompletionEnum.EXECUTING){
				CompletionEnum completeStatus = quest.getManifestation().tick(dt);
				if(completeStatus != CompletionEnum.EXECUTING){
					status.setCompleted(completeStatus);
					completeQuest(quest, status);
					statusChanged = true;
				}
			}else
				break;
		}
		if(statusChanged)
			Collections.sort(statuses, new QuestStatus.CompletionComparator());
	}
	
	private static void completeQuest(GDXQuest quest, QuestStatus status){
		if(quest.isRepeatable())
			for(AbstractQuestTrigger trigger : quest.getTriggers())
				if(trigger.getName().matches(quest.getRepeatableTriggerReset()))
					trigger.reinitialize();
	}
	
	/**
	 * The following works because of how java .equals works. I give it
	 * a QuestStatus that matches. Also, booleans default to 'false' so if
	 * the dependent quest is not completed, it will match, and return 
	 * false
	 * @return true if the quest's prerequisites have been completed
	 */
	public boolean isActive(GDXQuest quest){
		if(!quest.getPrerequisites().trim().equals(""))
			for(String prereq : quest.getPrerequisites().split(",")){
				List statuses = levelQuestStatusMap.get(currentLevel.getName());
				for(QuestStatus status : statuses)
					if(status.levelName.equals(currentLevel.getName()) && prereq.trim().equals(status.questName) &&
							status.getCompleted() != CompletionEnum.COMPLETED)
						return false;
			}
		return true;
	}
	
	public boolean isCompleted(GDXQuest quest){
		QuestStatus representative = new QuestStatus(currentLevel.getName(), quest.getName());
		representative.setCompleted(CompletionEnum.COMPLETED);
		return levelQuestStatusMap.get(currentLevel.getName()).contains(representative);
	}
	
	public void setStatus(String questName, CompletionEnum completed){
		List statuses = levelQuestStatusMap.get(currentLevel.getName());
		for(QuestStatus status : statuses)
			if(status.questName.equals(questName))
				status.setCompleted(completed);
		Collections.sort(statuses, new QuestStatus.CompletionComparator());
	}
	
	public List getQuestStatuses(){
		return getQuestStatuses(currentLevel);
	}
	
	public List getQuestStatuses(GDXLevel level){
		return levelQuestStatusMap.get(level.getName());
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy