import { GameConfig } from "./config.js"; const QUEST_TEMPLATES = [ { descriptionKey: "questPlaceEggs", targetKey: "eggsPlaced", targetBase: 3 }, { descriptionKey: "questEarnCoins", targetKey: "coinsEarned", targetBase: 100 }, { descriptionKey: "questSellAnimals", targetKey: "animalsSold", targetBase: 2 }, { descriptionKey: "questUpgradeConveyor", targetKey: "conveyorUpgrades", targetBase: 1 }, { descriptionKey: "questUpgradePlot", targetKey: "plotUpgrades", targetBase: 1 }, ]; /** * @param {string} dateKey YYYY-MM-DD * @returns {number} */ function daySeed(dateKey) { let h = 0; for (let i = 0; i < dateKey.length; i++) h = (h * 31 + dateKey.charCodeAt(i)) >>> 0; return h; } /** * @param {import("./types.js").GameState} state * @param {number} level * @returns {number} */ function _questReward(state, level) { return GameConfig.Quests.RewardBase + level * GameConfig.Quests.RewardPerLevel; } /** * @param {import("./types.js").GameState} state * @returns {import("./types.js").Quest[]} */ export function generateDailyQuests(state) { const today = new Date().toISOString().slice(0, 10); if (state.lastQuestDay === today && state.quests?.length > 0) return state.quests; state.lastQuestDay = today; let seed = daySeed(today); const rng = () => { seed = (seed * 1103515245 + 12345) >>> 0; return (seed >>> 16) / 65536; }; const shuffled = [...QUEST_TEMPLATES].sort(() => rng() - 0.5); const count = Math.min(GameConfig.Quests.CountPerDay, shuffled.length); const level = (state.prestigeLevel ?? 0) + state.plotLevel + state.conveyorLevel; state.quests = shuffled.slice(0, count).map((q, i) => ({ id: `q-${today}-${i}`, descriptionKey: q.descriptionKey, target: q.targetBase, current: 0, reward: GameConfig.Quests.RewardBase + level * GameConfig.Quests.RewardPerLevel, done: false, })); return state.quests; } /** @param {import("./types.js").GameState} state */ function getQuestProgress(state) { const s = state.stats ?? { eggsPlaced: 0, animalsSold: 0, conveyorUpgrades: 0, plotUpgrades: 0, coinsEarned: 0 }; return { eggsPlaced: s.eggsPlaced ?? 0, animalsSold: s.animalsSold ?? 0, conveyorUpgrades: s.conveyorUpgrades ?? 0, plotUpgrades: s.plotUpgrades ?? 0, coinsEarned: s.coinsEarned ?? 0, }; } /** * @param {import("./types.js").GameState} state * @returns {number} coins awarded from completed quests this tick */ export function tickQuests(state) { generateDailyQuests(state); const progress = getQuestProgress(state); let earned = 0; for (const q of state.quests ?? []) { if (q.done) { // already done } else { let current = null; if (q.descriptionKey === "questPlaceEggs") current = progress.eggsPlaced; else if (q.descriptionKey === "questSellAnimals") current = progress.animalsSold; else if (q.descriptionKey === "questUpgradeConveyor") current = progress.conveyorUpgrades; else if (q.descriptionKey === "questUpgradePlot") current = progress.plotUpgrades; else if (q.descriptionKey === "questEarnCoins") current = progress.coinsEarned ?? 0; if (current !== null && current !== undefined) { q.current = Math.min(current, q.target); if (q.current >= q.target) { q.done = true; earned += q.reward; } } } } state.coins += earned; return earned; }