Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: QuestGraph #60

Merged
63 changes: 63 additions & 0 deletions core/src/main/java/com/gdx/game/quest/FetchQuestTaskHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.gdx.game.quest;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.gdx.game.entities.Entity;
import com.gdx.game.entities.EntityConfig;
import com.gdx.game.map.MapManager;
import com.gdx.game.profile.ProfileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FetchQuestTaskHandler implements QuestTaskHandler {

private static final Logger LOGGER = LoggerFactory.getLogger(QuestGraph.class);

@Override
public void handleUpdate(QuestTask questTask, String questID) {
String taskConfig = questTask.getPropertyValue(QuestTask.QuestTaskPropertyType.TARGET_TYPE.toString());
if (taskConfig == null || taskConfig.isEmpty())
return;
EntityConfig config = Entity.getEntityConfig(taskConfig);

Array<Vector2> questItemPositions = ProfileManager.getInstance().getProperty(config.getEntityID(), Array.class);
//Case where all the items have been picked up
if (questItemPositions != null && questItemPositions.size == 0) {
questTask.setTaskComplete();
LOGGER.debug("TASK : {} is complete of Quest: {}", questTask.getId(), questID);
LOGGER.debug("INFO : {}", QuestTask.QuestTaskPropertyType.TARGET_TYPE);
}
}

@Override
public void handleInit(MapManager mapManager, QuestTask questTask, String questID) {

String taskConfig = questTask.getPropertyValue(QuestTask.QuestTaskPropertyType.TARGET_TYPE.toString());
if (taskConfig == null || taskConfig.isEmpty())
return;

Array<Entity> questEntities = new Array<>();
Array<Vector2> positions = mapManager.getQuestItemSpawnPositions(questID, questTask.getId());
EntityConfig config = Entity.getEntityConfig(taskConfig);
Array<Vector2> questItemPositions = ProfileManager.getInstance().getProperty(config.getEntityID(), Array.class);

if (questItemPositions == null) {
questItemPositions = new Array<>(positions);
addQuestEntities(config, positions, questID, questEntities);
} else {
addQuestEntities(config, positions, questID, questEntities);
}

mapManager.addMapQuestEntities(questEntities);
ProfileManager.getInstance().setProperty(config.getEntityID(), questItemPositions);
}

private void addQuestEntities(EntityConfig config, Array<Vector2> positions, String questID, Array<Entity> questEntities) {
for (Vector2 position : positions) {
Entity entity = Entity.initEntity(config, position);
entity.getEntityConfig().setCurrentQuestID(questID);
questEntities.add(entity);
}
}

}
235 changes: 63 additions & 172 deletions core/src/main/java/com/gdx/game/quest/QuestGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
import com.badlogic.gdx.utils.Json;
import com.gdx.game.entities.Entity;
import com.gdx.game.entities.EntityConfig;
import com.gdx.game.map.MapFactory;
import com.gdx.game.map.MapManager;
import com.gdx.game.profile.ProfileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Set;
import java.util.*;
alexandrecorlet marked this conversation as resolved.
Show resolved Hide resolved

public class QuestGraph {

Expand All @@ -28,6 +25,11 @@ public class QuestGraph {
private int goldReward;
private int xpReward;

public QuestGraph() {
alexandrecorlet marked this conversation as resolved.
Show resolved Hide resolved
questTasks = new Hashtable<>();
questTaskDependencies = new Hashtable<>();
}

public int getGoldReward() {
return goldReward;
}
Expand Down Expand Up @@ -79,10 +81,6 @@ public boolean areAllTasksComplete() {
}

public void setTasks(Hashtable<String, QuestTask> questTasks) {
if (questTasks.size() < 0) {
throw new IllegalArgumentException("Can't have a negative amount of conversations");
}

this.questTasks = questTasks;
this.questTaskDependencies = new Hashtable<>(questTasks.size());

Expand All @@ -107,59 +105,35 @@ public boolean isValid(String taskID) {
}

public boolean isReachable(String sourceID, String sinkID) {
if (!isValid(sourceID) || !isValid(sinkID)) {
return false;
}
if (questTasks.get(sourceID) == null) {
return false;
}
Set<String> reachableNodes = new HashSet<>();
return isReachable(sourceID, sinkID, reachableNodes);
}

ArrayList<QuestTaskDependency> list = questTaskDependencies.get(sourceID);
if (list == null) {
return false;
}
for(QuestTaskDependency dependency: list) {
if (dependency.getSourceId().equalsIgnoreCase(sourceID) && dependency.getDestinationId().equalsIgnoreCase(sinkID)) {
private boolean isReachable(String sourceId, String targetId, Set<String> reachableNodes) {
if (sourceId.equals(targetId))
return true;

reachableNodes.add(sourceId);
List<QuestTaskDependency> dependencies = questTaskDependencies.computeIfAbsent(sourceId, k -> new ArrayList<>());
for (QuestTaskDependency dep : dependencies) {
String destinationId = dep.getDestinationId();
if (!reachableNodes.contains(destinationId) && isReachable(destinationId, targetId, reachableNodes))
return true;
}
}

return false;
}

public QuestTask getQuestTaskByID(String id) {
if (!isValid(id)) {
//System.out.println("Id " + id + " is not valid!");
return null;
}
return questTasks.get(id);
return (isValid(id)) ? questTasks.get(id) : null;
}

public void addDependency(QuestTaskDependency questTaskDependency) {
ArrayList<QuestTaskDependency> list = questTaskDependencies.get(questTaskDependency.getSourceId());
if (list == null) {
return;
}

//Will not add if creates cycles
if (doesCycleExist(questTaskDependency)) {
//System.out.println("Cycle exists! Not adding");
return;
}

String sourceId = questTaskDependency.getSourceId();
ArrayList<QuestTaskDependency> list = questTaskDependencies.computeIfAbsent(sourceId, k -> new ArrayList<>());
list.add(questTaskDependency);
}

public boolean doesCycleExist(QuestTaskDependency questTaskDep) {
Set<String> keys = questTasks.keySet();
for(String id: keys) {
if (doesQuestTaskHaveDependencies(id) && questTaskDep.getDestinationId().equalsIgnoreCase(id)) {
//System.out.println("ID: " + id + " destID: " + questTaskDep.getDestinationId());
return true;
}
}
return false;
}

public boolean doesQuestTaskHaveDependencies(String id) {
QuestTask task = getQuestTaskByID(id);
if (task == null) {
Expand All @@ -176,40 +150,30 @@ public boolean updateQuestForReturn() {

//First, see if all tasks are available, meaning no blocking dependencies
for(QuestTask task : tasks) {
if (!isQuestTaskAvailable(task.getId())) {
if (isQuestTaskAvailable(task.getId()) && !task.isTaskComplete() && task.getQuestType().equals(QuestTask.QuestType.RETURN)) {
readyTask = task;
readyTask.setTaskComplete();
} else {
return false;
}
if (!task.isTaskComplete()) {
if (task.getQuestType().equals(QuestTask.QuestType.RETURN)) {
readyTask = task;
} else {
return false;
}
}
}
if (readyTask == null) {
return false;
}
readyTask.setTaskComplete();
return true;

return readyTask != null;
}

public boolean isQuestTaskAvailable(String id) {
QuestTask task = getQuestTaskByID(id);
if (task == null) {
if (task == null)
return false;
}
ArrayList<QuestTaskDependency> list = questTaskDependencies.get(id);

for(QuestTaskDependency dep: list) {
QuestTask depTask = getQuestTaskByID(dep.getDestinationId());
if (depTask == null || depTask.isTaskComplete()) {
continue;
}
if (dep.getSourceId().equalsIgnoreCase(id)) {
ArrayList<QuestTaskDependency> list = questTaskDependencies.get(id);
for (QuestTaskDependency dep : list) {
QuestTask depTask = getQuestTaskByID(dep.getSourceId());
if (depTask != null && !depTask.isTaskComplete() && dep.getSourceId().equalsIgnoreCase(task.getId())) {
return false;
}
}

return true;
}

Expand All @@ -225,119 +189,46 @@ public void update(MapManager mapMgr) {
ArrayList<QuestTask> allQuestTasks = getAllQuestTasks();
for(QuestTask questTask: allQuestTasks) {

if (questTask.isTaskComplete()) {
continue;
}

//We first want to make sure the task is available and is relevant to current location
if (!isQuestTaskAvailable(questTask.getId())) {
continue;
}
if (isInvalidQuestTask(questTask, mapMgr)) continue;

String taskLocation = questTask.getPropertyValue(QuestTask.QuestTaskPropertyType.TARGET_LOCATION.toString());
if (taskLocation == null || taskLocation.isEmpty() || !taskLocation.equalsIgnoreCase(mapMgr.getCurrentMapType().toString())) {
continue;
}
// Determine the handler based on quest type
QuestTaskHandler handler = getHandlerForQuestType(questTask.getQuestType());
if (handler != null)
handler.handleUpdate(questTask, questID);
}
}

switch(questTask.getQuestType()) {
case FETCH:
String taskConfig = questTask.getPropertyValue(QuestTask.QuestTaskPropertyType.TARGET_TYPE.toString());
if (taskConfig == null || taskConfig.isEmpty()) {
break;
}
EntityConfig config = Entity.getEntityConfig(taskConfig);

Array<Vector2> questItemPositions = ProfileManager.getInstance().getProperty(config.getEntityID(), Array.class);
if (questItemPositions == null) {
break;
}

//Case where all the items have been picked up
if (questItemPositions.size == 0) {
questTask.setTaskComplete();
LOGGER.debug("TASK : {} is complete of Quest: {}", questTask.getId(), questID);
LOGGER.debug("INFO : {}", QuestTask.QuestTaskPropertyType.TARGET_TYPE);
}
break;
case KILL:
break;
case DELIVERY:
break;
case GUARD:
break;
case ESCORT:
break;
case RETURN:
break;
case DISCOVER:
break;
}
private QuestTaskHandler getHandlerForQuestType(QuestTask.QuestType questType) {
switch (questType) {
case FETCH:
return new FetchQuestTaskHandler();
hdescottes marked this conversation as resolved.
Show resolved Hide resolved
default:
return null;
}
}

public void init(MapManager mapMgr) {
ArrayList<QuestTask> allQuestTasks = getAllQuestTasks();
for(QuestTask questTask: allQuestTasks) {

if (questTask.isTaskComplete()) {
continue;
}
if (isInvalidQuestTask(questTask, mapMgr)) continue;

//We first want to make sure the task is available and is relevant to current location
if (!isQuestTaskAvailable(questTask.getId())) {
continue;
}
// Determine the handler based on quest type
QuestTaskHandler handler = getHandlerForQuestType(questTask.getQuestType());
if (handler != null)
handler.handleInit(mapMgr, questTask, questID);
}
}

String taskLocation = questTask.getPropertyValue(QuestTask.QuestTaskPropertyType.TARGET_LOCATION.toString());
if (taskLocation == null || taskLocation.isEmpty() || !taskLocation.equalsIgnoreCase(mapMgr.getCurrentMapType().toString())) {
continue;
}
private boolean isInvalidQuestTask(QuestTask questTask, MapManager mapManager) {
if (questTask.isTaskComplete() || !isQuestTaskAvailable(questTask.getId()))
return true;

switch(questTask.getQuestType()) {
case FETCH:
Array<Entity> questEntities = new Array<>();
Array<Vector2> positions = mapMgr.getQuestItemSpawnPositions(questID, questTask.getId());
String taskConfig = questTask.getPropertyValue(QuestTask.QuestTaskPropertyType.TARGET_TYPE.toString());
if (taskConfig == null || taskConfig.isEmpty()) {
break;
}
EntityConfig config = Entity.getEntityConfig(taskConfig);

Array<Vector2> questItemPositions = ProfileManager.getInstance().getProperty(config.getEntityID(), Array.class);

if (questItemPositions == null) {
questItemPositions = new Array<>();
for(Vector2 position: positions) {
questItemPositions.add(position);
Entity entity = Entity.initEntity(config, position);
entity.getEntityConfig().setCurrentQuestID(questID);
questEntities.add(entity);
}
} else {
for(Vector2 questItemPosition: questItemPositions) {
Entity entity = Entity.initEntity(config, questItemPosition);
entity.getEntityConfig().setCurrentQuestID(questID);
questEntities.add(entity);
}
}

mapMgr.addMapQuestEntities(questEntities);
ProfileManager.getInstance().setProperty(config.getEntityID(), questItemPositions);
break;
case KILL:
break;
case DELIVERY:
break;
case GUARD:
break;
case ESCORT:
break;
case RETURN:
break;
case DISCOVER:
break;
}
}
QuestTask.QuestTaskPropertyType questTaskPropertyType = QuestTask.QuestTaskPropertyType.TARGET_LOCATION;
String taskLocation = questTask.getPropertyValue(questTaskPropertyType.toString());
MapFactory.MapType mapType = mapManager.getCurrentMapType();

return taskLocation == null || taskLocation.isEmpty() || !taskLocation.equalsIgnoreCase(mapType.toString());
}

public String toString() {
Expand Down
11 changes: 11 additions & 0 deletions core/src/main/java/com/gdx/game/quest/QuestTaskHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.gdx.game.quest;

import com.gdx.game.map.MapManager;

public interface QuestTaskHandler {

void handleUpdate(QuestTask questTask, String questID);

void handleInit(MapManager mapManager, QuestTask questTask, String questID);

}
Loading
Loading