Adventure - quest code refactoring

This commit is contained in:
jjayers99
2023-12-31 10:56:16 -05:00
parent 008de375f3
commit 3de20add60
7 changed files with 290 additions and 526 deletions

View File

@@ -5,8 +5,11 @@ import com.badlogic.gdx.utils.Array;
import forge.adventure.character.EnemySprite; import forge.adventure.character.EnemySprite;
import forge.adventure.pointofintrest.PointOfInterest; import forge.adventure.pointofintrest.PointOfInterest;
import forge.adventure.scene.GameScene; import forge.adventure.scene.GameScene;
import forge.adventure.scene.TileMapScene;
import forge.adventure.stage.GameHUD; import forge.adventure.stage.GameHUD;
import forge.adventure.stage.MapStage;
import forge.adventure.util.AdventureQuestController; import forge.adventure.util.AdventureQuestController;
import forge.adventure.util.AdventureQuestEvent;
import forge.adventure.util.Current; import forge.adventure.util.Current;
import forge.adventure.world.WorldSave; import forge.adventure.world.WorldSave;
import forge.util.Aggregates; import forge.util.Aggregates;
@@ -116,7 +119,7 @@ public class AdventureQuestData implements Serializable {
//Temporarily allow only one active stage until parallel stages and prerequisites are implemented //Temporarily allow only one active stage until parallel stages and prerequisites are implemented
for (AdventureQuestStage stage : stages) { for (AdventureQuestStage stage : stages) {
if (stage.getStatus() == Active ) { if (stage.getStatus() == ACTIVE) {
toReturn.add(stage); toReturn.add(stage);
} }
} }
@@ -127,7 +130,7 @@ public class AdventureQuestData implements Serializable {
List<AdventureQuestStage> toReturn = new ArrayList<>(); List<AdventureQuestStage> toReturn = new ArrayList<>();
for (AdventureQuestStage stage : stages) { for (AdventureQuestStage stage : stages) {
if (stage.getStatus() == Complete) if (stage.getStatus() == COMPLETE)
toReturn.add(stage); toReturn.add(stage);
} }
return toReturn; return toReturn;
@@ -350,22 +353,18 @@ public class AdventureQuestData implements Serializable {
{ {
ArrayList<EnemyData> matchesTags = new ArrayList<>(); ArrayList<EnemyData> matchesTags = new ArrayList<>();
for(EnemyData data: new Array.ArrayIterator<>(WorldData.getAllEnemies())) { for(EnemyData data: new Array.ArrayIterator<>(WorldData.getAllEnemies())) {
boolean valid = true; ArrayList<String> candidateTags = new ArrayList<>(Arrays.asList(data.questTags));
List<String> candidateTags = Arrays.asList(data.questTags); int tagCount = candidateTags.size();
for (String tag : stage.enemyTags) {
if (!candidateTags.contains(tag)) { candidateTags.removeAll(stage.enemyExcludeTags);
valid = false; if (candidateTags.size() != tagCount) {
break; continue;
}
} }
for (String tag : stage.enemyExcludeTags) {
if (candidateTags.contains(tag)) { candidateTags.removeAll(stage.enemyTags);
valid = false; if (candidateTags.size() == tagCount - stage.enemyTags.size()) {
break;
}
}
if (valid)
matchesTags.add(data); matchesTags.add(data);
}
} }
if (matchesTags.isEmpty()){ if (matchesTags.isEmpty()){
return new EnemyData(Aggregates.random(WorldData.getAllEnemies())); return new EnemyData(Aggregates.random(WorldData.getAllEnemies()));
@@ -375,216 +374,32 @@ public class AdventureQuestData implements Serializable {
} }
} }
public void updateEnteredPOI(PointOfInterest arrivedAt){
class questUpdate {
}
public void updateStages(AdventureQuestEvent event){
boolean done = true; boolean done = true;
if (event.poi == null && MapStage.getInstance().isInMap())
event.poi = TileMapScene.instance().rootPoint;
for (AdventureQuestStage stage: stages) { for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) { switch (stage.getStatus()) {
case Active: case ACTIVE:
done = stage.updateEnterPOI(arrivedAt) == Complete && done; done = stage.handleEvent(event) == COMPLETE && done;
break; break;
case Complete: case COMPLETE:
continue; continue;
default: default:
done = false; done = false;
break; break;
} }
failed |= stage.getStatus() == FAILED;
} }
completed = done; completed = done;
} }
public void updateReputationChanged(PointOfInterest location, int newReputation) {
boolean done = true;
for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) {
case Active:
done = stage.updateReputationChanged(location, newReputation) == Complete && done;
break;
case Complete:
continue;
default:
done = false;
break;
}
}
completed = done;
}
public void updateMapFlag(String mapFlag, int flagValue){
boolean done = true;
for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) {
case Active:
done = stage.updateMapFlag(mapFlag, flagValue) == Complete && done;
break;
case Inactive:
done = false;
break;
}
}
completed = done;
}
public void updateCharacterFlag(String characterFlag, int flagValue){
boolean done = true;
for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) {
case Active:
done = stage.updateCharacterFlag(characterFlag, flagValue) == Complete && done;
break;
case Inactive:
done = false;
break;
}
}
completed = done;
}
public void updateQuestFlag(String questFlag, int flagValue){
boolean done = true;
for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) {
case Active:
done = stage.updateQuestFlag(questFlag, flagValue) == Complete && done;
break;
case Inactive:
done = false;
break;
}
}
completed = done;
}
public void updateLeave(){
boolean done = true;
for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) {
case Active:
done = stage.updateLeave() == Complete && done;
break;
case Inactive:
done = false;
break;
}
}
completed = done;
}
public void updateWin(EnemySprite defeated, boolean cleared){
boolean done = true;
for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) {
case Active:
done = stage.updateWin(defeated, cleared) == Complete && done;
break;
case Complete:
continue;
default:
done = false;
break;
}
}
completed = done;
}
public void updateLose(EnemySprite defeatedBy){
for (AdventureQuestStage stage: stages) {
if (stage.getStatus() != Active)
continue;
failed = stage.updateLose(defeatedBy) == Failed;
}
}
public void updateDespawn(EnemySprite despawned){
for (AdventureQuestStage stage: stages) {
if (stage.getStatus() != Active)
continue;
failed = stage.updateDespawn(despawned)== Failed || failed;
}
}
public void updateArenaComplete(boolean winner){
for (AdventureQuestStage stage: stages) {
if(failed)
break;
if (stage.getStatus() != Active)
continue;
stage.updateArenaComplete(winner);
failed = failed || stage.getStatus() == Failed;
}
if (!failed)
updateStatus();
}
public void updateEventComplete(AdventureEventData completedEvent) {
for (AdventureQuestStage stage: stages) {
if(failed)
break;
if (stage.getStatus() != Active)
continue;
stage.updateEventComplete(completedEvent);
failed = failed || stage.getStatus() == Failed;
}
if (!failed)
updateStatus();
}
public void updateQuestComplete(AdventureQuestData completedQuest) {
for (AdventureQuestStage stage: stages) {
if(failed)
break;
if (stage.getStatus() != Active)
continue;
stage.updateQuestComplete(completedQuest);
failed = failed || stage.getStatus() == Failed;
}
if (!failed)
updateStatus();
}
public void updateItemUsed(ItemData data) {
for (AdventureQuestStage stage: stages) {
if(failed)
break;
if (stage.getStatus() != Active)
continue;
stage.updateItemUsed(data);
failed = failed || stage.getStatus() == Failed;
}
if (!failed)
updateStatus();
}
public void updateItemReceived(ItemData data) {
for (AdventureQuestStage stage: stages) {
if(failed)
break;
if (stage.getStatus() != Active)
continue;
stage.updateItemReceived(data);
failed = failed || stage.getStatus() == Failed;
}
if (!failed)
updateStatus();
}
public void updateStatus(){
for (AdventureQuestStage stage: stages) {
switch (stage.getStatus()) {
case Complete:
continue;
case Failed:
failed = true;
break;
case None:
case Inactive:
case Active:
return;
}
}
completed = true;
}
public DialogData getPrologue() { public DialogData getPrologue() {
if (!prologueDisplayed) { if (!prologueDisplayed) {
prologueDisplayed = true; prologueDisplayed = true;
@@ -610,9 +425,9 @@ public class AdventureQuestData implements Serializable {
public void activateNextStages() { public void activateNextStages() {
boolean showNotification = false; boolean showNotification = false;
for (AdventureQuestStage s : stages) { for (AdventureQuestStage s : stages) {
if (s.getStatus() == Inactive){ if (s.getStatus() == INACTIVE){
s.checkPrerequisites(getCompletedStageIDs()); s.checkPrerequisites(getCompletedStageIDs());
if (s.getStatus() == Active) { if (s.getStatus() == ACTIVE) {
AdventureQuestController.instance().addQuestSprites(s); AdventureQuestController.instance().addQuestSprites(s);
showNotification = true; showNotification = true;
} }

View File

@@ -2,12 +2,12 @@ package forge.adventure.data;
import forge.adventure.character.EnemySprite; import forge.adventure.character.EnemySprite;
import forge.adventure.pointofintrest.PointOfInterest; import forge.adventure.pointofintrest.PointOfInterest;
import forge.adventure.pointofintrest.PointOfInterestChanges;
import forge.adventure.scene.TileMapScene; import forge.adventure.scene.TileMapScene;
import forge.adventure.stage.MapStage; import forge.adventure.stage.MapStage;
import forge.adventure.util.AdventureQuestController; import forge.adventure.util.AdventureQuestController;
import forge.adventure.util.AdventureQuestEvent;
import forge.adventure.util.AdventureQuestEventType;
import forge.adventure.util.Current; import forge.adventure.util.Current;
import forge.adventure.world.WorldSave;
import forge.util.Aggregates; import forge.util.Aggregates;
import java.io.Serializable; import java.io.Serializable;
@@ -22,7 +22,7 @@ public class AdventureQuestStage implements Serializable {
private static final long serialVersionUID = 12042023L; private static final long serialVersionUID = 12042023L;
public int id; public int id;
private AdventureQuestController.QuestStatus status = Inactive; private AdventureQuestController.QuestStatus status = INACTIVE;
public String name = ""; public String name = "";
public String description = ""; public String description = "";
public boolean anyPOI = false; //false: Pick one PoI. True: Any PoI matching tags is usable public boolean anyPOI = false; //false: Pick one PoI. True: Any PoI matching tags is usable
@@ -67,14 +67,14 @@ public class AdventureQuestStage implements Serializable {
} }
public void checkPrerequisites(List<Integer> completedStages) { public void checkPrerequisites(List<Integer> completedStages) {
if (status != Inactive) if (status != INACTIVE)
return; return;
for (Integer prereqID : prerequisiteIDs) { for (Integer prereqID : prerequisiteIDs) {
if (!completedStages.contains(prereqID)) { if (!completedStages.contains(prereqID)) {
return; return;
} }
} }
status = Active; status = ACTIVE;
} }
public AdventureQuestController.QuestStatus getStatus() { public AdventureQuestController.QuestStatus getStatus() {
@@ -153,135 +153,6 @@ public class AdventureQuestStage implements Serializable {
targetSprite = target; targetSprite = target;
} }
public AdventureQuestController.QuestStatus updateEnterPOI(PointOfInterest entered) {
if (status != Active || !checkIfTargetLocation()) {
return status;
}
switch (objective) {
case Delivery:
status = Complete;
break;
case Travel:
status = ++progress1 >= count3 ? Complete : status;
break;
case HaveReputationInCurrentLocation:
PointOfInterestChanges changes = WorldSave.getCurrentSave().getPointOfInterestChanges(entered.getID());
status = changes.getMapReputation() >= count1 ? Complete : status;
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateReputationChanged(PointOfInterest location, int newReputation) {
if (status != Active)
return status;
switch (objective) {
case HaveReputation:
status = checkIfTargetLocation(location) && newReputation >= count1 ? Complete : status;
break;
case HaveReputationInCurrentLocation:
status = checkIfTargetLocation() && newReputation >= count1 ? Complete : status;
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateCharacterFlag(String flagName, int flagValue) {
//Not yet implemented as objective type
//Could theoretically be used as a part of quests for character lifetime achievements
// if (status != Active) {
// return status;
// }
// if (objective == CharacterFlag) {
// if (flagName.equals(this.mapFlag) && flagValue >= this.mapFlagValue)
// status = Complete;
// }
return status;
}
public AdventureQuestController.QuestStatus updateQuestFlag(String flagName, int flagValue) {
if (status != Active) {
return status;
}
switch (objective) {
case QuestFlag:
status = flagName.equals(this.mapFlag) && flagValue >= this.mapFlagValue ? Complete : status;
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateMapFlag(String mapFlag, int mapFlagValue) {
if (status != Active) {
return status;
}
switch (objective) {
case MapFlag:
status = checkIfTargetLocation() && mapFlag.equals(mapFlag) && mapFlagValue >= this.mapFlagValue ? Complete : status;
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateLeave() {
if (status != Active) {
return status;
}
switch (objective) {
case Leave:
status = checkIfTargetLocation() && ++progress1 >= count1 ? Complete : status;
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateWin(EnemySprite defeated, boolean mapCleared) {
//todo - Does this need to also be called for alternate mob removal types?
if (status != Active) {
return status;
}
switch (objective) {
case Clear:
status = mapCleared && checkIfTargetLocation()? Complete : status;
break;
case Defeat:
if (!checkIfTargetLocation())
return status;
if (mixedEnemies) {
List<String> defeatedTags = Arrays.asList(defeated.getData().questTags);
for (String targetTag : enemyTags) {
if (!defeatedTags.contains(targetTag)) {
//Does not count toward objective
return status;
}
}
for (String targetTag : enemyExcludeTags) {
if (defeatedTags.contains(targetTag)) {
//Does not count
return status;
}
}
} else {
if (!defeated.getData().getName().equals(targetEnemyData.getName()))
//Does not count
return status;
}
//All tags matched, kill confirmed
if (++progress1 >= count1) {
status = Complete;
}
break;
case Hunt:
status = defeated.equals(targetSprite)? Complete : status;
break;
}
return status;
}
public boolean checkIfTargetLocation() { public boolean checkIfTargetLocation() {
return checkIfTargetLocation(TileMapScene.instance().rootPoint); return checkIfTargetLocation(TileMapScene.instance().rootPoint);
} }
@@ -305,151 +176,24 @@ public class AdventureQuestStage implements Serializable {
return anyPOI; return anyPOI;
} }
public AdventureQuestController.QuestStatus updateLose(EnemySprite defeatedBy) { public boolean checkIfTargetEnemy(EnemySprite enemy) {
if (status != Active) { if (targetEnemyData != null) {
return status; return enemy.getData() == targetEnemyData;
} }
switch (objective) { else if (targetSprite == null) {
case Defeat: ArrayList<String> candidateTags = new ArrayList<>(Arrays.asList(enemy.getData().questTags));
{ int tagCount = candidateTags.size();
if (mixedEnemies) {
List<String> defeatedByTags = Arrays.asList(defeatedBy.getData().questTags); candidateTags.removeAll(enemyExcludeTags);
for (String targetTag : enemyTags) { if (candidateTags.size() != tagCount) {
if (!defeatedByTags.contains(targetTag)) { return false;
//Does not count
return status;
}
}
for (String targetTag : enemyExcludeTags) {
if (defeatedByTags.contains(targetTag)) {
//Does not count
return status;
}
}
} else {
if (defeatedBy.getData() != targetEnemyData)
//Does not count
return status;
}
//All tags matched
//progress2: number of times defeated by a matching enemy
//count2: if > 0, fail once defeated this many times
if (status == Active && ++progress2 >= count2 && count2 > 0) {
status = Failed;
}
break;
} }
case Hunt:
if (defeatedBy.equals(targetSprite)) {
status = Failed;
}
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateDespawn(EnemySprite despawned) { candidateTags.removeAll(enemyTags);
if (status != Active) { return candidateTags.size() == tagCount - enemyTags.size();
return status; } else {
return targetSprite.equals(enemy);
} }
switch (objective) {
case Hunt:
status = (despawned.equals(targetSprite))? Failed : status;
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateArenaComplete(boolean winner) {
if (status != Active || !checkIfTargetLocation()) {
return status;
}
if (objective == Arena) {
if (winner) {
status = ++progress1 >= count1 ? Complete : status;
} else {
status = ++progress2 >= count2 ? Failed : status;
}
}
return status;
}
public AdventureQuestController.QuestStatus updateEventComplete(AdventureEventData completedEvent) {
if (status != Active || !checkIfTargetLocation()) {
return status;
}
switch (objective) {
case EventFinish:
if (++progress1 >= count1) {
status = Complete;
}
break;
case EventWinMatches:
progress1 += completedEvent.matchesWon;
progress2 += completedEvent.matchesLost;
if (++progress2 >= count2 && count2 > 0) {
status = Failed;
} else if (++progress1 >= count1) {
status = Complete;
}
break;
case EventWin:
if (completedEvent.playerWon) {
status = ++progress1 >=count1 ? Complete : status;
} else {
status = ++progress2 >= count2 && count2 > 0 ? Failed : status;
}
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateQuestComplete(AdventureQuestData completedQuest) {
if (status != Active) {
return status;
}
switch (objective) {
case CompleteQuest:
if (this.anyPOI) {
//todo - filter based on POI tags, below implementation is wrong but no quests use it yet
// List<String> completedQuestPOITags = Arrays.stream(completedQuest.questPOITags).collect(Collectors.toList());
// for (String targetTag : POITags) {
// if (!completedQuestPOITags.contains(targetTag)) {
// return status;
// }
// }
//All tags matched, completed quest came from valid POI.
} else {
if (!completedQuest.sourceID.equals(this.targetPOI.getID()))
return status;
}
status = ++progress1 >= count1 ? Complete : status;
break;
}
return status;
}
public AdventureQuestController.QuestStatus updateItemUsed(ItemData data) {
if (status != Active) {
return status;
}
if (objective == Use) {
status = (itemNames.isEmpty()) || itemNames.contains(data.name) && ++progress1 >= count1 ? Complete : status;
}
return status;
}
public AdventureQuestController.QuestStatus updateItemReceived(ItemData data) {
if (status != Active) {
return status;
}
if (objective == Fetch) {
status = (itemNames.isEmpty()) || itemNames.contains(data.name) && ++progress1 >= count1 ? Complete : status;
}
return status;
} }
public AdventureQuestStage() { public AdventureQuestStage() {
@@ -516,4 +260,112 @@ public class AdventureQuestStage implements Serializable {
} }
return validPOIs; return validPOIs;
} }
public AdventureQuestController.QuestStatus handleEvent(AdventureQuestEvent event) {
if (!checkIfTargetLocation(event.poi))
return status;
if (event.enemy != null && !checkIfTargetEnemy(event.enemy))
return status;
switch (objective) {
case CharacterFlag:
if (event.type == AdventureQuestEventType.CHARACTERFLAG)
status = event.flagName != null && event.flagName.equals(this.mapFlag) && event.flagValue >= this.mapFlagValue ? COMPLETE : status;
break;
case CompleteQuest:
status = event.type == AdventureQuestEventType.QUESTCOMPLETE
&& (anyPOI || event.otherQuest != null && event.otherQuest.sourceID.equals(targetPOI.getID()))
&& ++progress1 >= count1 ? COMPLETE : status;
break;
case Clear:
if (!event.clear) {
break;
}
//intentional fallthrough to DEFEAT
case Defeat:
if (event.type != AdventureQuestEventType.MATCHCOMPLETE)
break;
if (event.winner) {
status = ++progress1 >= count1 ? COMPLETE : status;
} else {
status = ++progress2 >= count2 ? FAILED : status;
}
case Arena:
status = event.type == AdventureQuestEventType.EVENTCOMPLETE
&& event.clear //if event not conceded
&& ++progress1 >= count1 ? COMPLETE : status;
break;
case EventWin:
if (event.type != AdventureQuestEventType.EVENTCOMPLETE)
break;
if (event.winner)
event.count1++; //number of wins
else
event.count2++; //number of losses
if (++progress2 >= count2 && count2 > 0) {
status = FAILED;
} else if (++progress1 >= count1) {
status = COMPLETE;
}
break;
case EventWinMatches:
if (event.type != AdventureQuestEventType.EVENTMATCHCOMPLETE)
break;
if (event.winner) {
status = ++progress1 >=count1 ? COMPLETE : status;
} else {
status = ++progress2 >= count2 && count2 > 0 ? FAILED : status;
}
break;
case Fetch:
status = event.type == AdventureQuestEventType.RECEIVEITEM
&& (itemNames.isEmpty()) || (event.item != null && itemNames.contains(event.item.name))
&& ++progress1 >= count1 ? COMPLETE : status;
break;
case Hunt:
if (event.type == AdventureQuestEventType.DESPAWN) {
status = event.enemy.equals(targetSprite) ? FAILED : status;
} else if (event.type == AdventureQuestEventType.MATCHCOMPLETE) {
if (event.winner) {
status = event.enemy.equals(targetSprite) ? COMPLETE : status;
} else {
status = ++progress2 >= count2 && count2 > 0 ? FAILED : status;
}
}
break;
case Leave:
if (event.type == AdventureQuestEventType.LEAVEPOI)
status = ++progress1 >= count1 ? COMPLETE : status;
break;
case MapFlag:
if (event.type == AdventureQuestEventType.MAPFLAG)
status = event.flagName != null && event.flagName.equals(this.mapFlag) && event.flagValue >= this.mapFlagValue ? COMPLETE : status;
break;
case QuestFlag:
if (event.type == AdventureQuestEventType.QUESTFLAG)
status = event.flagName != null && event.flagName.equals(this.mapFlag) && event.flagValue >= this.mapFlagValue ? COMPLETE : status;
break;
case HaveReputation:
//presumed that WorldMapOK will be set on this type, as reputation will occasionally be updated remotely by quests
if (event.type == AdventureQuestEventType.REPUTATION)
status = checkIfTargetLocation(event.poi) && event.count1 >= count1 ? COMPLETE : status;
break;
case HaveReputationInCurrentLocation:
if (event.type == AdventureQuestEventType.ENTERPOI || event.type == AdventureQuestEventType.REPUTATION)
status = event.count1 >= count1 ? COMPLETE : status;
break;
case Delivery:
//will eventually differentiate from Travel
case Travel:
status = ++progress3 >= count3 ? COMPLETE : status;
break;
case Use:
status = event.type == AdventureQuestEventType.USEITEM
&& (itemNames.isEmpty()) || itemNames.contains(event.item.name)
&& ++progress1 >= count1 ? COMPLETE : status;
break;
}
return status;
}
} }

View File

@@ -70,7 +70,7 @@ public class QuestLogScene extends UIScene {
root.add(scroller).colspan(3); root.add(scroller).colspan(3);
root.align(Align.right); root.align(Align.right);
root.row(); root.row();
Label column0Label = new Label("Quest Name", Controls.getSkin()); Label column0Label = new Label(Forge.getLocalizer().getMessage("lblQuestName"), Controls.getSkin());
column0Label.setColor(Color.BLACK); column0Label.setColor(Color.BLACK);
root.add(column0Label).align(Align.bottomLeft); root.add(column0Label).align(Align.bottomLeft);
root.row(); root.row();
@@ -115,7 +115,7 @@ public class QuestLogScene extends UIScene {
nameLabel.setWrap(true); nameLabel.setWrap(true);
nameLabel.setColor(Color.BLACK); nameLabel.setColor(Color.BLACK);
scrollContainer.add(nameLabel).align(Align.left).expandX(); scrollContainer.add(nameLabel).align(Align.left).expandX();
Button details = Controls.newTextButton("Details"); Button details = Controls.newTextButton(Forge.getLocalizer().getMessage("lblDetails"));
details.addListener( new ClickListener(){ details.addListener( new ClickListener(){
public void clicked(InputEvent event, float x, float y){ public void clicked(InputEvent event, float x, float y){
loadDetailsPane(quest); loadDetailsPane(quest);
@@ -145,7 +145,7 @@ public class QuestLogScene extends UIScene {
detailRoot.setVisible(true); detailRoot.setVisible(true);
detailScrollContainer.clear(); detailScrollContainer.clear();
detailScrollContainer.row(); detailScrollContainer.row();
trackButton.setText(quest.isTracked?"Untrack Quest":"Track Quest"); trackButton.setText(quest.isTracked?Forge.getLocalizer().getMessage("lblUntrackQuest"):Forge.getLocalizer().getMessage("lblTrackQuest"));
trackButton.addListener( new ClickListener(){ trackButton.addListener( new ClickListener(){
public void clicked(InputEvent event, float x, float y){ public void clicked(InputEvent event, float x, float y){
toggleTracked(quest); toggleTracked(quest);
@@ -156,7 +156,7 @@ public class QuestLogScene extends UIScene {
abandonQuestButton.addListener( new ClickListener(){ abandonQuestButton.addListener( new ClickListener(){
public void clicked(InputEvent event, float x, float y){ public void clicked(InputEvent event, float x, float y){
Dialog confirm = createGenericDialog("", "Abandon Quest?","Yes","No", () -> abandonQuest(quest), null); Dialog confirm = createGenericDialog("", Forge.getLocalizer().getMessage("lblAbandonQuestConfirm"),Forge.getLocalizer().getMessage("lblYes"),Forge.getLocalizer().getMessage("lblNo"), () -> abandonQuest(quest), null);
showDialog(confirm); showDialog(confirm);
} }
}); });
@@ -211,10 +211,10 @@ public class QuestLogScene extends UIScene {
private void toggleTracked(AdventureQuestData quest){ private void toggleTracked(AdventureQuestData quest){
if (quest.isTracked){ if (quest.isTracked){
quest.isTracked = false; quest.isTracked = false;
trackButton.setText("Track Quest"); trackButton.setText(Forge.getLocalizer().getMessage("lblTrackQuest"));
} else { } else {
AdventureQuestController.trackQuest(quest); AdventureQuestController.trackQuest(quest);
trackButton.setText("Untrack Quest"); trackButton.setText(Forge.getLocalizer().getMessage("lblUntrackQuest"));
} }
} }

View File

@@ -19,6 +19,8 @@ import java.time.LocalDate;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static forge.adventure.util.AdventureQuestController.QuestStatus.*;
public class AdventureQuestController implements Serializable { public class AdventureQuestController implements Serializable {
public static void trackQuest(AdventureQuestData quest) { public static void trackQuest(AdventureQuestData quest) {
@@ -31,7 +33,7 @@ public class AdventureQuestController implements Serializable {
List<EnemyData> extraSpawns = new ArrayList<>(); List<EnemyData> extraSpawns = new ArrayList<>();
for (AdventureQuestData q : Current.player().getQuests()) { for (AdventureQuestData q : Current.player().getQuests()) {
for (AdventureQuestStage c : q.stages) { for (AdventureQuestStage c : q.stages) {
if (c.getStatus().equals(QuestStatus.Active) && c.objective.equals(ObjectiveTypes.Defeat)) { if (c.getStatus().equals(ACTIVE) && c.objective.equals(ObjectiveTypes.Defeat)) {
if (c.getTargetEnemyData() != null) { if (c.getTargetEnemyData() != null) {
extraSpawns.add(c.getTargetEnemyData()); extraSpawns.add(c.getTargetEnemyData());
continue; continue;
@@ -65,7 +67,7 @@ public class AdventureQuestController implements Serializable {
Map<String,Float> boostedSpawns = new HashMap<>(); Map<String,Float> boostedSpawns = new HashMap<>();
for (AdventureQuestData q : Current.player().getQuests()){ for (AdventureQuestData q : Current.player().getQuests()){
for (AdventureQuestStage c : q.stages){ for (AdventureQuestStage c : q.stages){
if (c.getStatus().equals(QuestStatus.Active) && c.objective.equals(ObjectiveTypes.Defeat)) if (c.getStatus().equals(ACTIVE) && c.objective.equals(ObjectiveTypes.Defeat))
{ {
List<String> toBoost = new ArrayList<>(); List<String> toBoost = new ArrayList<>();
if (c.mixedEnemies){ if (c.mixedEnemies){
@@ -108,6 +110,7 @@ public class AdventureQuestController implements Serializable {
public enum ObjectiveTypes{ public enum ObjectiveTypes{
None, None,
Arena, Arena,
CharacterFlag,
Clear, Clear,
CompleteQuest, CompleteQuest,
Defeat, Defeat,
@@ -134,11 +137,11 @@ public class AdventureQuestController implements Serializable {
} }
public enum QuestStatus{ public enum QuestStatus{
None, NONE,
Inactive, INACTIVE,
Active, ACTIVE,
Complete, COMPLETE,
Failed FAILED
} }
private Map<String, Long> nextQuestDate = new HashMap<>(); private Map<String, Long> nextQuestDate = new HashMap<>();
private int maximumSideQuests = 5; //todo: move to configuration file private int maximumSideQuests = 5; //todo: move to configuration file
@@ -164,19 +167,19 @@ public class AdventureQuestController implements Serializable {
} }
for (AdventureQuestStage questStage : quest.stages) for (AdventureQuestStage questStage : quest.stages)
{ {
if (questStage.getStatus() == QuestStatus.Inactive) if (questStage.getStatus() == INACTIVE)
continue; continue;
if (questStage.prologue != null && (!questStage.prologue.text.isEmpty()) && !questStage.prologueDisplayed){ if (questStage.prologue != null && (!questStage.prologue.text.isEmpty()) && !questStage.prologueDisplayed){
questStage.prologueDisplayed = true; questStage.prologueDisplayed = true;
dialogQueue.add(questStage.prologue); dialogQueue.add(questStage.prologue);
} }
if (questStage.getStatus() == QuestStatus.Failed && questStage.failureDialog != null && !questStage.failureDialog.text.isEmpty()){ if (questStage.getStatus() == FAILED && questStage.failureDialog != null && !questStage.failureDialog.text.isEmpty()){
dialogQueue.add(questStage.failureDialog); dialogQueue.add(questStage.failureDialog);
continue; continue;
} }
if (questStage.getStatus() == QuestStatus.Complete && questStage.epilogue != null && (!questStage.epilogue.text.isEmpty()) && !questStage.epilogueDisplayed){ if (questStage.getStatus() == COMPLETE && questStage.epilogue != null && (!questStage.epilogue.text.isEmpty()) && !questStage.epilogueDisplayed){
questStage.epilogueDisplayed = true; questStage.epilogueDisplayed = true;
dialogQueue.add(questStage.epilogue); dialogQueue.add(questStage.epilogue);
} }
@@ -320,40 +323,56 @@ public class AdventureQuestController implements Serializable {
public void updateEnteredPOI(PointOfInterest arrivedAt) public void updateEnteredPOI(PointOfInterest arrivedAt)
{ {
AdventureQuestEvent event = new AdventureQuestEvent();
event.type = AdventureQuestEventType.ENTERPOI;
event.poi = arrivedAt;
for(AdventureQuestData currentQuest : Current.player().getQuests()) { for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateEnteredPOI(arrivedAt); currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateQuestsMapFlag(String updatedMapFlag, int updatedFlagValue) public void updateQuestsMapFlag(String updatedMapFlag, int updatedFlagValue)
{ {
AdventureQuestEvent event = new AdventureQuestEvent();
event.type = AdventureQuestEventType.MAPFLAG;
event.flagName = updatedMapFlag;
event.flagValue = updatedFlagValue;
for(AdventureQuestData currentQuest : Current.player().getQuests()) { for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateMapFlag(updatedMapFlag, updatedFlagValue); currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateQuestsCharacterFlag(String updatedCharacterFlag, int updatedCharacterFlagValue) public void updateQuestsCharacterFlag(String updatedCharacterFlag, int updatedCharacterFlagValue)
{ {
AdventureQuestEvent event = new AdventureQuestEvent();
event.type = AdventureQuestEventType.CHARACTERFLAG;
event.flagName = updatedCharacterFlag;
event.flagValue = updatedCharacterFlagValue;
for(AdventureQuestData currentQuest : Current.player().getQuests()) { for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateCharacterFlag(updatedCharacterFlag, updatedCharacterFlagValue); currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateQuestsQuestFlag(String updatedQuestFlag, int updatedQuestFlagValue) public void updateQuestsQuestFlag(String updatedQuestFlag, int updatedQuestFlagValue)
{ {
AdventureQuestEvent event = new AdventureQuestEvent();
event.type = AdventureQuestEventType.QUESTFLAG;
event.flagName = updatedQuestFlag;
event.flagValue = updatedQuestFlagValue;
for(AdventureQuestData currentQuest : Current.player().getQuests()) { for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateQuestFlag(updatedQuestFlag, updatedQuestFlagValue); currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateQuestsLeave(){ public void updateQuestsLeave(){
AdventureQuestEvent event = new AdventureQuestEvent();
event.type = AdventureQuestEventType.LEAVEPOI;
for(AdventureQuestData currentQuest : Current.player().getQuests()) { for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateLeave(); currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
@@ -375,8 +394,13 @@ public class AdventureQuestController implements Serializable {
} }
} }
} }
AdventureQuestEvent event = new AdventureQuestEvent();
event.type = AdventureQuestEventType.MATCHCOMPLETE;
event.winner = true;
event.enemy = defeated;
event.clear = allEnemiesCleared;
for(AdventureQuestData currentQuest : Current.player().getQuests()) { for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateWin(defeated, allEnemiesCleared); currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
@@ -386,51 +410,75 @@ public class AdventureQuestController implements Serializable {
public void updateQuestsLose(EnemySprite defeatedBy){ public void updateQuestsLose(EnemySprite defeatedBy){
enemySpriteList.remove(defeatedBy); enemySpriteList.remove(defeatedBy);
AdventureQuestEvent event = new AdventureQuestEvent();
event.type = AdventureQuestEventType.MATCHCOMPLETE;
event.winner = false;
event.enemy = defeatedBy;
event.clear = false;
for(AdventureQuestData currentQuest : Current.player().getQuests()) { for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateLose(defeatedBy); currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateDespawn(EnemySprite despawned){ public void updateDespawn(EnemySprite despawned){
enemySpriteList.remove(despawned); enemySpriteList.remove(despawned);
for(AdventureQuestData currentQuest: Current.player().getQuests()) { AdventureQuestEvent event = new AdventureQuestEvent();
currentQuest.updateDespawn(despawned); event.type = AdventureQuestEventType.DESPAWN;
event.enemy = despawned;
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateArenaComplete(boolean winner){ public void updateArenaComplete(boolean winner){
for(AdventureQuestData currentQuest: Current.player().getQuests()) { AdventureQuestEvent event = new AdventureQuestEvent();
currentQuest.updateArenaComplete(winner); event.type = AdventureQuestEventType.ARENACOMPLETE;
event.winner = winner;
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateEventComplete(AdventureEventData completedEvent) { public void updateEventComplete(AdventureEventData completedEvent) {
for(AdventureQuestData currentQuest: Current.player().getQuests()) { AdventureQuestEvent event = new AdventureQuestEvent();
currentQuest.updateEventComplete(completedEvent); event.type = AdventureQuestEventType.EVENTCOMPLETE;
event.winner = completedEvent.playerWon;
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateQuestComplete(AdventureQuestData completedQuest) { public void updateQuestComplete(AdventureQuestData completedQuest) {
for(AdventureQuestData currentQuest: Current.player().getQuests()) { AdventureQuestEvent event = new AdventureQuestEvent();
currentQuest.updateQuestComplete(completedQuest); event.type = AdventureQuestEventType.QUESTCOMPLETE;
event.otherQuest = completedQuest;
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateItemUsed(ItemData data) { public void updateItemUsed(ItemData data) {
for(AdventureQuestData currentQuest: Current.player().getQuests()) { AdventureQuestEvent event = new AdventureQuestEvent();
currentQuest.updateItemUsed(data); event.type = AdventureQuestEventType.USEITEM;
event.item = data;
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }
public void updateItemReceived(ItemData data) { public void updateItemReceived(ItemData data) {
for(AdventureQuestData currentQuest: Current.player().getQuests()) { AdventureQuestEvent event = new AdventureQuestEvent();
currentQuest.updateItemReceived(data); event.type = AdventureQuestEventType.RECEIVEITEM;
event.item = data;
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
currentQuest.updateStages(event);
} }
activateNextStages(); activateNextStages();
} }

View File

@@ -0,0 +1,21 @@
package forge.adventure.util;
import forge.adventure.character.EnemySprite;
import forge.adventure.data.AdventureQuestData;
import forge.adventure.data.ItemData;
import forge.adventure.pointofintrest.PointOfInterest;
public class AdventureQuestEvent {
public AdventureQuestEventType type;
public PointOfInterest poi;
public EnemySprite enemy;
public ItemData item;
public Boolean clear;
public Boolean winner;
public String flagName;
public int flagValue;
public int count1;
public int count2;
public AdventureQuestData otherQuest;
}

View File

@@ -0,0 +1,20 @@
package forge.adventure.util;
public enum AdventureQuestEventType {
ENTERPOI,
REPUTATION,
MAPFLAG,
QUESTFLAG,
CHARACTERFLAG,
LEAVEPOI,
MATCHCOMPLETE,
QUESTCOMPLETE,
DESPAWN,
ARENACOMPLETE,
ARENAMATCHCOMPLETE,
EVENTCOMPLETE,
EVENTMATCHCOMPLETE,
RECEIVEITEM,
USEITEM
}

View File

@@ -2976,6 +2976,14 @@ lblWinLossRatio=Win Loss Ratio
lblHeal=Heal lblHeal=Heal
lblTempHitPoints=Temporary Hit Points lblTempHitPoints=Temporary Hit Points
lblEndAdventureEventConfirm=This will end the current event, and your entry fee will not be refunded.\n\nLeave anyway? lblEndAdventureEventConfirm=This will end the current event, and your entry fee will not be refunded.\n\nLeave anyway?
#Adventure Quest Log
lblAbandonQuest=Abandon Quest
lblTrackQuest=Track Quest
lblUntrackQuest=Untrack Quest
lblQuestList=Quest List
lblQuestName=Quest Name
lblAbandonQuestConfirm=Abandon Quest?
lblDetails=Details
#CardDetailUtil.java #CardDetailUtil.java
lblChosenColors=Chosen colors: lblChosenColors=Chosen colors:
lblLoyalty=Loyalty lblLoyalty=Loyalty