Release v0.1.3 2026-07-11
This commit is contained in:
+54
-63
@@ -1,7 +1,15 @@
|
||||
import type { BossCollection, GameModeId, GameSettings, HunterSave, SaveSlotId } from "./types";
|
||||
import { BOSS_ORDER } from "../game/bossCatalog";
|
||||
import { BOSS_DEFINITIONS, BOSS_ORDER } from "../game/bossCatalog";
|
||||
import { createClassInventory } from "../game/healers";
|
||||
import type { BossId } from "../game/types";
|
||||
import { createDefaultGearProgress } from "../game/progression/gear";
|
||||
import {
|
||||
BOSS_DROP_TABLES,
|
||||
createEmptyCollectionLog,
|
||||
type CollectionLog,
|
||||
type LootRarity,
|
||||
type MaterialStack,
|
||||
} from "../game/progression/loot";
|
||||
|
||||
export const DEFAULT_SETTINGS: GameSettings = {
|
||||
masterVolume: 80,
|
||||
@@ -10,52 +18,39 @@ export const DEFAULT_SETTINGS: GameSettings = {
|
||||
largeText: false,
|
||||
};
|
||||
|
||||
export const DEFAULT_COLLECTIONS: BossCollection[] = [
|
||||
{
|
||||
bossId: "bulldrome",
|
||||
bossName: "Bulldrome",
|
||||
defeated: true,
|
||||
drops: [
|
||||
{ id: "bull-horn", name: "Cinder Horn", icon: "♜", rarity: "Common", count: 7 },
|
||||
{ id: "bull-hide", name: "Ember Hide", icon: "▧", rarity: "Uncommon", count: 3 },
|
||||
{ id: "bull-idol", name: "Vault Idol", icon: "◇", rarity: "Rare", count: 1 },
|
||||
{ id: "bull-heart", name: "Furnace Heart", icon: "✦", rarity: "Mythic", count: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
bossId: "vexa",
|
||||
bossName: "Vexa",
|
||||
defeated: false,
|
||||
drops: [
|
||||
{ id: "vexa-silk", name: "Living Silk", icon: "⌁", rarity: "Common", count: 0 },
|
||||
{ id: "vexa-venom", name: "Widow Venom", icon: "✣", rarity: "Uncommon", count: 0 },
|
||||
{ id: "vexa-eye", name: "Loom Eye", icon: "◉", rarity: "Rare", count: 0 },
|
||||
{ id: "vexa-heart", name: "Webmother Heart", icon: "✦", rarity: "Mythic", count: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
bossId: "cindermaw",
|
||||
bossName: "Cindermaw",
|
||||
defeated: true,
|
||||
drops: [
|
||||
{ id: "maw-scale", name: "Soot Scale", icon: "◈", rarity: "Common", count: 4 },
|
||||
{ id: "maw-gland", name: "Mending Gland", icon: "+", rarity: "Uncommon", count: 2 },
|
||||
{ id: "maw-crest", name: "Ashen Crest", icon: "⌁", rarity: "Rare", count: 0 },
|
||||
{ id: "maw-breath", name: "Bottled Breath", icon: "☀", rarity: "Mythic", count: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
bossId: "ember-mantis-duelist",
|
||||
bossName: "Ember Mantis Duelist",
|
||||
defeated: false,
|
||||
drops: [
|
||||
{ id: "mantis-chitin", name: "Ember Chitin", icon: "◇", rarity: "Common", count: 0 },
|
||||
{ id: "mantis-edge", name: "Cinderblade Edge", icon: "⚔", rarity: "Uncommon", count: 0 },
|
||||
{ id: "mantis-antenna", name: "Duelist Antenna", icon: "⌁", rarity: "Rare", count: 0 },
|
||||
{ id: "mantis-core", name: "Molten Mantis Core", icon: "✦", rarity: "Mythic", count: 0 },
|
||||
],
|
||||
},
|
||||
];
|
||||
const RARITY_LABELS: Record<LootRarity, BossCollection["drops"][number]["rarity"]> = {
|
||||
common: "Common",
|
||||
uncommon: "Uncommon",
|
||||
rare: "Rare",
|
||||
epic: "Epic",
|
||||
legendary: "Legendary",
|
||||
};
|
||||
|
||||
export function buildCollections(collectionLog: CollectionLog, bossKills: Record<string, number>): BossCollection[] {
|
||||
return BOSS_ORDER.map((bossId) => {
|
||||
const table = BOSS_DROP_TABLES[bossId];
|
||||
return {
|
||||
bossId,
|
||||
bossName: BOSS_DEFINITIONS[bossId].name,
|
||||
defeated: (bossKills[bossId] ?? 0) > 0,
|
||||
drops: table.entries.map((drop) => ({
|
||||
id: drop.id,
|
||||
name: drop.name,
|
||||
icon: drop.glyph,
|
||||
rarity: RARITY_LABELS[drop.rarity],
|
||||
count: drop.kind === "coin"
|
||||
? collectionLog.dropsFound[drop.id] ?? 0
|
||||
: collectionLog.petsFound[drop.id] ?? 0,
|
||||
chance: drop.chanceLabel,
|
||||
itemLevel: drop.kind === "coin" ? drop.itemLevel : undefined,
|
||||
kind: drop.kind,
|
||||
})),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export const DEFAULT_COLLECTION_LOG: CollectionLog = createEmptyCollectionLog();
|
||||
export const DEFAULT_COLLECTIONS: BossCollection[] = buildCollections(DEFAULT_COLLECTION_LOG, {});
|
||||
|
||||
export const MODE_COPY: Record<GameModeId, { eyebrow: string; title: string; description: string; detail: string; status: string }> = {
|
||||
"roguelike-pve": {
|
||||
@@ -69,7 +64,7 @@ export const MODE_COPY: Record<GameModeId, { eyebrow: string; title: string; des
|
||||
eyebrow: "1–4 hunters · chosen encounter",
|
||||
title: "Dungeons",
|
||||
description: "Choose a guardian, review its mechanics, and bring a prepared healing loadout into a focused encounter.",
|
||||
detail: "Bulldrome · Vexa · Cindermaw · Ember Mantis",
|
||||
detail: "Ten prototype guardians available",
|
||||
status: "Playable now",
|
||||
},
|
||||
"roguelike-pvp": {
|
||||
@@ -92,12 +87,6 @@ export function selectRandomBoss(random: () => number = Math.random): BossId {
|
||||
return BOSS_ORDER[Math.floor(random() * BOSS_ORDER.length)] ?? BOSS_ORDER[0];
|
||||
}
|
||||
|
||||
export function selectRandomBossPair(random: () => number = Math.random): readonly [BossId, BossId] {
|
||||
const firstIndex = Math.floor(random() * BOSS_ORDER.length) % BOSS_ORDER.length;
|
||||
const secondOffset = 1 + Math.floor(random() * (BOSS_ORDER.length - 1));
|
||||
return [BOSS_ORDER[firstIndex], BOSS_ORDER[(firstIndex + secondOffset) % BOSS_ORDER.length]];
|
||||
}
|
||||
|
||||
export const MAX_HUNTER_NAME_LENGTH = 20;
|
||||
|
||||
export function normalizeHunterName(value: string): string {
|
||||
@@ -112,25 +101,27 @@ export function createHunterSave(slotId: SaveSlotId, now: string, hunterName: st
|
||||
const normalizedName = normalizeHunterName(hunterName);
|
||||
if (!normalizedName) throw new Error("Hunter name is required.");
|
||||
return {
|
||||
schemaVersion: 2,
|
||||
schemaVersion: 4,
|
||||
slotId,
|
||||
hunterName: normalizedName,
|
||||
activeClassId: "priest",
|
||||
healers: {
|
||||
priest: { level: 12, inventory: createClassInventory("priest") },
|
||||
priest: { level: 1, inventory: createClassInventory("priest") },
|
||||
druid: { level: 1, inventory: createClassInventory("druid") },
|
||||
shaman: { level: 1, inventory: createClassInventory("shaman") },
|
||||
},
|
||||
location: "Ember Vault Approach",
|
||||
playSeconds: 8 * 60 * 60 + 42 * 60,
|
||||
playSeconds: 0,
|
||||
updatedAt: now,
|
||||
stats: {
|
||||
totalBossKills: 16,
|
||||
flawlessClears: 5,
|
||||
alliesSaved: 143,
|
||||
healingDone: 284_650,
|
||||
bossKills: { Bulldrome: 12, Vexa: 0, Cindermaw: 4, "Ember Mantis Duelist": 0 },
|
||||
totalBossKills: 0,
|
||||
flawlessClears: 0,
|
||||
alliesSaved: 0,
|
||||
healingDone: 0,
|
||||
bossKills: {},
|
||||
},
|
||||
collections: structuredClone(DEFAULT_COLLECTIONS),
|
||||
materials: [] as MaterialStack[],
|
||||
collectionLog: createEmptyCollectionLog(),
|
||||
gearProgress: createDefaultGearProgress(),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user