feat: add daily challenges system

Three PST-midnight-resetting challenges generated deterministically per
day from click, boss, quest, and prestige types. Progress tracked
server-side for bosses and prestige, client-side for clicks and quests.
Crystal rewards awarded on completion and preserved through prestige resets.
This commit is contained in:
2026-03-06 22:22:18 -08:00
committed by Naomi Carrigan
parent a7d4b72805
commit aaeece1a18
15 changed files with 462 additions and 8 deletions
+20 -1
View File
@@ -1,4 +1,5 @@
import type { Achievement, Equipment, GameState } from "@elysium/types";
import { updateChallengeProgress } from "../utils/dailyChallenges.js";
/**
* Checks all achievements against the current game state and returns an updated
@@ -198,6 +199,23 @@ export const applyTick = (state: GameState, deltaSeconds: number): GameState =>
});
}
// Count quests newly completed this tick and update daily challenge progress
const newlyCompletedQuestCount = updatedQuests.filter(
(q, i) => q.status === "completed" && state.quests[i]?.status !== "completed",
).length;
let updatedDailyChallenges = state.dailyChallenges;
let challengeCrystals = 0;
if (updatedDailyChallenges && newlyCompletedQuestCount > 0) {
const result = updateChallengeProgress(
updatedDailyChallenges,
"questsCompleted",
newlyCompletedQuestCount,
);
updatedDailyChallenges = result.updatedChallenges;
challengeCrystals = result.crystalsAwarded;
}
const newGold = capResource(state.resources.gold + goldGained + questGold);
const newEssence = capResource(state.resources.essence + essenceGained + questEssence);
const newTotalGoldEarned = state.player.totalGoldEarned + goldGained + questGold;
@@ -208,8 +226,9 @@ export const applyTick = (state: GameState, deltaSeconds: number): GameState =>
...state.resources,
gold: newGold,
essence: newEssence,
crystals: capResource(state.resources.crystals + questCrystals),
crystals: capResource(state.resources.crystals + questCrystals + challengeCrystals),
},
dailyChallenges: updatedDailyChallenges,
player: {
...state.player,
totalGoldEarned: newTotalGoldEarned,