feat: add exploration and crafting systems

Adds two new game systems: Exploration (scouts collect materials from
timed area runs) and Crafting (combine materials into permanent
multipliers). Includes 72 exploration areas, 54 materials, 36 recipes,
and 108 new Codex lore entries. Removes unused characterName requirement
from prestige/transcendence/apotheosis reset flows.
This commit is contained in:
2026-03-07 04:14:04 -08:00
committed by Naomi Carrigan
parent 2aa6362ad6
commit 6ddf8e0b43
35 changed files with 4722 additions and 94 deletions
+18
View File
@@ -1,4 +1,15 @@
export type { ApotheosisData } from "./interfaces/Apotheosis.js";
export type { CraftingBonusType, CraftingMaterialRequirement, CraftingRecipe } from "./interfaces/CraftingRecipe.js";
export type {
ExplorationArea,
ExplorationAreaState,
ExplorationEvent,
ExplorationEventEffect,
ExplorationEventEffectType,
ExplorationMaterialDrop,
ExplorationState,
} from "./interfaces/Exploration.js";
export type { Material, MaterialRarity } from "./interfaces/Material.js";
export type { CodexEntry, CodexState } from "./interfaces/Codex.js";
export type {
Achievement,
@@ -19,6 +30,13 @@ export type {
BuyEchoUpgradeResponse,
BuyPrestigeUpgradeRequest,
BuyPrestigeUpgradeResponse,
CraftRecipeRequest,
CraftRecipeResponse,
ExploreCollectEventResult,
ExploreCollectRequest,
ExploreCollectResponse,
ExploreStartRequest,
ExploreStartResponse,
GiteaRelease,
LoadResponse,
PrestigeRequest,
+45 -9
View File
@@ -67,9 +67,7 @@ export interface BossChallengeResponse {
}>;
}
export interface PrestigeRequest {
characterName: string;
}
export type PrestigeRequest = Record<string, never>;
export interface PrestigeResponse {
runestones: number;
@@ -129,9 +127,7 @@ export interface UpdateProfileResponse {
profileSettings: ProfileSettings;
}
export interface TranscendenceRequest {
characterName: string;
}
export type TranscendenceRequest = Record<string, never>;
export interface TranscendenceResponse {
echoes: number;
@@ -152,9 +148,7 @@ export interface BuyEchoUpgradeResponse {
echoMetaMultiplier: number;
}
export interface ApotheosisRequest {
characterName: string;
}
export type ApotheosisRequest = Record<string, never>;
export interface ApotheosisResponse {
newApotheosisCount: number;
@@ -176,5 +170,47 @@ export interface AboutResponse {
releases: GiteaRelease[];
}
export interface ExploreStartRequest {
areaId: string;
}
export interface ExploreStartResponse {
areaId: string;
endsAt: number;
}
export interface ExploreCollectRequest {
areaId: string;
}
export interface ExploreCollectEventResult {
text: string;
goldChange: number;
essenceChange: number;
materialGained: { materialId: string; quantity: number } | null;
adventurerLostCount: number;
}
export interface ExploreCollectResponse {
foundNothing: boolean;
nothingMessage?: string;
materialsFound: Array<{ materialId: string; quantity: number }>;
event: ExploreCollectEventResult | null;
}
export interface CraftRecipeRequest {
recipeId: string;
}
export interface CraftRecipeResponse {
recipeId: string;
bonusType: string;
bonusValue: number;
craftedGoldMultiplier: number;
craftedEssenceMultiplier: number;
craftedClickMultiplier: number;
craftedCombatMultiplier: number;
}
// Re-export for convenience
export type { ProfileSettings };
+1 -1
View File
@@ -2,7 +2,7 @@ export interface CodexEntry {
id: string;
title: string;
content: string;
sourceType: "boss" | "quest" | "equipment" | "adventurer" | "upgrade" | "prestige" | "zone";
sourceType: "boss" | "quest" | "equipment" | "adventurer" | "upgrade" | "prestige" | "zone" | "exploration" | "recipe";
sourceId: string;
zoneId: string;
}
@@ -0,0 +1,19 @@
export type CraftingBonusType = "gold_income" | "essence_income" | "click_power" | "combat_power";
export interface CraftingMaterialRequirement {
materialId: string;
quantity: number;
}
export interface CraftingRecipe {
id: string;
name: string;
description: string;
zoneId: string;
requiredMaterials: CraftingMaterialRequirement[];
bonus: {
type: CraftingBonusType;
/** Multiplicative bonus value, e.g. 1.1 = +10% */
value: number;
};
}
@@ -0,0 +1,67 @@
export type ExplorationEventEffectType =
| "gold_gain"
| "gold_loss"
| "essence_gain"
| "material_gain"
| "adventurer_loss";
export interface ExplorationEventEffect {
type: ExplorationEventEffectType;
/** Gold amount for gold_gain / gold_loss */
amount?: number;
/** Material ID for material_gain */
materialId?: string;
/** Quantity for material_gain */
quantity?: number;
/** Fraction (01) of total adventurers lost for adventurer_loss */
fraction?: number;
}
export interface ExplorationEvent {
id: string;
text: string;
effect: ExplorationEventEffect;
}
export interface ExplorationMaterialDrop {
materialId: string;
minQuantity: number;
maxQuantity: number;
/** Relative probability weight — higher = more likely */
weight: number;
}
export interface ExplorationArea {
id: string;
name: string;
description: string;
zoneId: string;
durationSeconds: number;
possibleMaterials: ExplorationMaterialDrop[];
events: ExplorationEvent[];
}
export interface ExplorationAreaState {
id: string;
status: "locked" | "available" | "in_progress" | "completed";
/** Unix timestamp when exploration started (set when status becomes in_progress) */
startedAt?: number;
/** True after the first successful collect — used for codex unlock detection */
completedOnce?: boolean;
}
export interface ExplorationState {
areas: ExplorationAreaState[];
/** Current material inventory */
materials: Array<{ materialId: string; quantity: number }>;
/** IDs of crafting recipes that have been crafted (resets on prestige) */
craftedRecipeIds: string[];
/** Pre-computed gold income multiplier from all crafted recipes */
craftedGoldMultiplier: number;
/** Pre-computed essence income multiplier from all crafted recipes */
craftedEssenceMultiplier: number;
/** Pre-computed click power multiplier from all crafted recipes */
craftedClickMultiplier: number;
/** Pre-computed combat power multiplier from all crafted recipes */
craftedCombatMultiplier: number;
}
@@ -4,6 +4,7 @@ import type { Boss } from "./Boss.js";
import type { ApotheosisData } from "./Apotheosis.js";
import type { CodexState } from "./Codex.js";
import type { DailyChallengeState } from "./DailyChallenge.js";
import type { ExplorationState } from "./Exploration.js";
import type { TranscendenceData } from "./Transcendence.js";
import type { Equipment } from "./Equipment.js";
import type { Player } from "./Player.js";
@@ -36,4 +37,6 @@ export interface GameState {
transcendence?: TranscendenceData;
/** Apotheosis (third prestige layer) state — optional for backwards compatibility */
apotheosis?: ApotheosisData;
/** Exploration and crafting state — optional for backwards compatibility */
exploration?: ExplorationState;
}
@@ -0,0 +1,9 @@
export type MaterialRarity = "common" | "uncommon" | "rare";
export interface Material {
id: string;
name: string;
description: string;
zoneId: string;
rarity: MaterialRarity;
}