diff --git a/src/App.vue b/src/App.vue index 153c1e0..6717ecf 100644 --- a/src/App.vue +++ b/src/App.vue @@ -84,6 +84,8 @@ import QuestExpUpgrade from "@/classes/guildUpgrades/QuestExpUpgrade"; import QuestGoldUpgrade from "@/classes/guildUpgrades/QuestGoldUpgrade"; import AutoFinishQuestsUpgrade from "@/classes/guildUpgrades/AutoFinishQuestsUpgrade"; import RecruitmentCapacityUpgrade from "@/classes/guildUpgrades/RecruitmentCapacityUpgrade"; +import QuestPhase from "@/classes/quests/QuestPhase"; +import {PhaseType} from "@/classes/quests/QuestPhaseType"; export default defineComponent({ name: "GuildView", @@ -121,23 +123,22 @@ export default defineComponent({ async updateMissives() { for (const missive of this.missives) { if (missive.adventurers.length < missive.maxAdventurers) { - missive.progressPoints = 0; + missive.phases.forEach(phase => { + phase.points = 0; + }); continue; } - for (const adventurerId in missive.adventurers) { - const adventurer = missive.adventurers[adventurerId]; - const attack = adventurer.getAttack(); - adventurer.busy = true; - missive.progressPoints = Math.min(missive.progressPoints + attack, missive.maxProgress); + for (const phase of missive.phases) { + if (phase.completed()) continue; + phase.tick(missive.adventurers); } if ( - missive.progressPoints >= missive.maxProgress + missive.isCompleted() && this.guild.autoFinishQuestsUpgrade.getRanksToAutoFinishQuestsIn().includes(missive.rank) ) { this.finalizeQuest(missive); } } - }, async checkForNewRecruit(currentTimestamp: number, cooldownModifier: number = 1) { const recruitCapacity = this.guild.recruitmentCapacity.getRecruitmentCapacity(); @@ -178,7 +179,6 @@ export default defineComponent({ delete this.adventurersForHire[adventurer.id]; }, finalizeQuest(missive: Quest) { - missive.progressPoints = 0; this.guild.gold += missive.goldReward; for (const adventurerId in missive.adventurers) { const adventurer = missive.adventurers[adventurerId]; @@ -257,9 +257,26 @@ export default defineComponent({ if (Array.isArray(saveData.missives)) { for (const data of saveData.missives) { - const quest = new Quest(data.id, getFromString(data.rank), data.title, data.text, data.maxProgress, data.expReward, data.goldReward); - quest.progressPoints = data.progressPoints; - if (data.adventurers.length > 0) { + const phases: Array = []; + if (Array.isArray(data.phases)) { + for (const phaseData of data.phases) { + const types: Array = []; + if (Array.isArray(phaseData.types)) { + for (const type of phaseData.types) { + try { + const phaseType = PhaseType[type as keyof typeof PhaseType]; + types.push(phaseType); + } catch (e) { + console.error("Error creating phase type", e); + } + } + } + const phase = new QuestPhase(types, phaseData.maxPoints, phaseData.points); + phases.push(phase); + } + } + const quest = new Quest(data.id, getFromString(data.rank), data.title, data.text, phases, data.expReward, data.goldReward); + if (Array.isArray(data?.adventurers)) { for (const adventurer of data.adventurers) { const adventurerId = adventurer.id; if (this.adventurers[adventurerId] == null) continue; diff --git a/src/GameData.ts b/src/GameData.ts index 39fd775..530392e 100644 --- a/src/GameData.ts +++ b/src/GameData.ts @@ -2,6 +2,8 @@ import {Guild} from "@/classes/Guild"; import {Adventurer} from "@/classes/Adventurer"; import {Quest} from "@/classes/quests/Quest"; import {getFromString, QuestRank} from "@/classes/QuestRank"; +import QuestPhase from "@/classes/quests/QuestPhase"; +import {PhaseType} from "@/classes/quests/QuestPhaseType"; export class GameData { guild: Guild; @@ -98,11 +100,36 @@ export async function loadAvailableQuests(): Promise<{ [key: string]: { [key: st for (const quest of questRankData) { const id = quest.id; + + const phases = [] as Array; + if (Array.isArray(quest?.phases)) { + for (const phase of quest.phases) { + const phaseTypes: PhaseType[] = []; + if (Array.isArray(phase?.types)) { + for (const type of phase.types) { + const phaseType = PhaseType[type as keyof typeof PhaseType]; + if (!phaseType) { + console.error(`Invalid phase type: ${type}`); + continue; + } + phaseTypes.push(phaseType); + } + } + phases.push(new QuestPhase( + phaseTypes, + phase.maxPoints, + 0, + )); + } + } + + quests[questRank][id] = new Quest( id, questRank, quest.title, quest.text, + phases, ); } } diff --git a/src/classes/quests/Quest.ts b/src/classes/quests/Quest.ts index e54a7af..d18d5e8 100644 --- a/src/classes/quests/Quest.ts +++ b/src/classes/quests/Quest.ts @@ -1,5 +1,6 @@ import type {Adventurer} from "@/classes/Adventurer"; import {QuestRank} from "@/classes/QuestRank"; +import QuestPhase from "@/classes/quests/QuestPhase"; export class Quest { id: string; @@ -7,9 +8,8 @@ export class Quest { title: string; text: string; adventurers: Array; + phases: QuestPhase[] = []; maxAdventurers: number; - progressPoints: number; - maxProgress: number; expReward: number; goldReward: number; @@ -18,7 +18,7 @@ export class Quest { rank: QuestRank, title: string, text: string, - maxProgress: number = 1, + phases: QuestPhase[], expReward: number = 0, goldReward: number = 0, maxAdventurers: number = 1 @@ -27,16 +27,46 @@ export class Quest { this.rank = rank; this.title = title; this.text = text; - this.maxProgress = maxProgress; this.expReward = expReward; this.goldReward = goldReward; - this.progressPoints = 0; this.adventurers = []; this.maxAdventurers = maxAdventurers; + for (const phase of phases) { + this.phases.push(new QuestPhase(Array.from(phase.types), phase.maxPoints, phase.points)); + } } getPercentProgress(): number { - return Math.round(this.progressPoints / this.maxProgress * 100); + let maxProgress = 0; + let progressPoints = 0; + for (const phase of this.phases) { + maxProgress += phase.maxPoints; + progressPoints += phase.points; + } + return Math.round(progressPoints / maxProgress * 100); + } + + isCompleted(): boolean { + for (const phase of this.phases) { + if (!phase.completed()) return false; + } + return true; + } + + getMaxProgress(): number { + let maxProgress = 0; + for (const phase of this.phases) { + maxProgress += phase.maxPoints; + } + return maxProgress; + } + + getProgress(): number { + let progressPoints = 0; + for (const phase of this.phases) { + progressPoints += phase.points; + } + return progressPoints; } } @@ -49,47 +79,47 @@ export class Quest { */ export function getQuestWithRewards(quest: Quest, expModifier: number = 1, goldModifier: number = 1) { - let maxProgress = 1; + let rewardValue = 1; switch (quest.rank) { case QuestRank.S: // at level 30 adventurers have ~6513 dps, this will take 30 seconds on level 30 - maxProgress = 195390; + rewardValue = 195390; break; case QuestRank.A: // at level 25 adventurers have ~2051 dps, this will take 15 seconds on level 25 - maxProgress = 30770; + rewardValue = 30770; break; case QuestRank.B: // at level 20 adventurers have ~645 dps, this will take 15 seconds on level 20 - maxProgress = 9690; + rewardValue = 9690; break; case QuestRank.C: // at level 15 adventurers have ~203 dps, this will take 15 seconds on level 15 - maxProgress = 3045; + rewardValue = 3045; break; case QuestRank.D: // at level 10 adventurers have ~64 dps, this will take 15 seconds on level 10 - maxProgress = 960; + rewardValue = 960; break; case QuestRank.E: // at level 5 adventurers have ~20 dps, this will take 15 seconds on level 5 - maxProgress = 300; + rewardValue = 300; break; case QuestRank.F: // at level 1 adventurers have ~8 dps, this will take 15 seconds on level 1 - maxProgress = 120; + rewardValue = 120; break; } - let goldReward = Math.floor(maxProgress/6 * goldModifier); - let expReward = Math.floor((Math.floor(maxProgress/120) - maxProgress/1000) * expModifier); + let goldReward = Math.floor(rewardValue/6 * goldModifier); + let expReward = Math.floor((Math.floor(rewardValue/120) - rewardValue/1000) * expModifier); // add some randomness to the rewards goldReward = Math.floor(randomNumberBetween(goldReward * 0.95, goldReward * 1.1)); expReward = Math.max(1, Math.floor(randomNumberBetween(expReward * 0.95, expReward * 1.2))); - return new Quest(quest.id, quest.rank, quest.title, quest.text, maxProgress, expReward, goldReward); + return new Quest(quest.id, quest.rank, quest.title, quest.text, quest.phases, expReward, goldReward); } function randomNumberBetween(min: number, max: number) { diff --git a/src/views/QuestView.vue b/src/views/QuestView.vue index 640b850..b77f977 100644 --- a/src/views/QuestView.vue +++ b/src/views/QuestView.vue @@ -2,17 +2,17 @@