generated from nhcarrigan/template
b886928e49
Titles are earned by reaching milestones (quests, bosses, gold, clicks, adventurers, guild, prestige, transcendence, apotheosis, achievements, longevity) and are permanent - never lost on prestige/transcendence/ apotheosis resets. 20 titles available at launch. Also fixes a pre-existing P2034 write-conflict on the load backfill path and the exactOptionalPropertyTypes violation in the quest failure handler.
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import type { GameState } from "@elysium/types";
|
|
import { TITLES } from "../data/titles.js";
|
|
|
|
export const checkAndUnlockTitles = (
|
|
currentUnlocked: string[],
|
|
state: GameState,
|
|
guildName: string,
|
|
createdAt: number,
|
|
): string[] => {
|
|
const metrics: Record<string, number | boolean> = {
|
|
totalClicks: state.player.totalClicks,
|
|
totalGoldEarned: state.player.totalGoldEarned,
|
|
bossesDefeated: state.bosses.filter((b) => b.status === "defeated").length,
|
|
questsCompleted: state.quests.filter((q) => q.status === "completed").length,
|
|
prestigeCount: state.prestige.count,
|
|
transcendenceCount: state.transcendence?.count ?? 0,
|
|
apotheosisCount: state.apotheosis?.count ?? 0,
|
|
adventurerTotal: state.adventurers.reduce((sum, a) => sum + a.count, 0),
|
|
achievementsUnlocked: state.achievements.filter((a) => a.unlockedAt !== null).length,
|
|
guildFounded: guildName.trim().length > 0,
|
|
playedDays: Math.floor((Date.now() - createdAt) / 86_400_000),
|
|
};
|
|
|
|
const newlyUnlocked: string[] = [];
|
|
|
|
for (const title of TITLES) {
|
|
if (currentUnlocked.includes(title.id)) continue;
|
|
|
|
const { type, amount } = title.condition;
|
|
let earned = false;
|
|
|
|
if (type === "guildFounded") {
|
|
earned = metrics.guildFounded === true;
|
|
} else if (amount !== undefined) {
|
|
earned = (metrics[type] as number) >= amount;
|
|
}
|
|
|
|
if (earned) {
|
|
newlyUnlocked.push(title.id);
|
|
}
|
|
}
|
|
|
|
return newlyUnlocked;
|
|
};
|
|
|
|
export const parseUnlockedTitles = (raw: unknown): string[] => {
|
|
if (Array.isArray(raw)) {
|
|
return raw.filter((item): item is string => typeof item === "string");
|
|
}
|
|
return [];
|
|
};
|