generated from nhcarrigan/template
feat: initial elysium idle game prototype
Sets up the full monorepo with pnpm workspaces. Includes shared types package, Hono API with Discord OAuth/JWT auth, Prisma v6 + MongoDB Atlas, and React + Vite frontend with game loop, five tabs, and Discord-linked save/load.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import type { Adventurer } from "@elysium/types";
|
||||
|
||||
export const DEFAULT_ADVENTURERS: Adventurer[] = [
|
||||
{
|
||||
id: "peasant",
|
||||
name: "Peasant",
|
||||
class: "warrior",
|
||||
level: 1,
|
||||
goldPerSecond: 0.1,
|
||||
essencePerSecond: 0,
|
||||
count: 0,
|
||||
unlocked: true,
|
||||
},
|
||||
{
|
||||
id: "militia",
|
||||
name: "Militia",
|
||||
class: "warrior",
|
||||
level: 2,
|
||||
goldPerSecond: 0.5,
|
||||
essencePerSecond: 0,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "apprentice",
|
||||
name: "Apprentice Mage",
|
||||
class: "mage",
|
||||
level: 3,
|
||||
goldPerSecond: 1.5,
|
||||
essencePerSecond: 0.01,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "scout",
|
||||
name: "Scout",
|
||||
class: "rogue",
|
||||
level: 4,
|
||||
goldPerSecond: 4,
|
||||
essencePerSecond: 0.02,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "acolyte",
|
||||
name: "Acolyte",
|
||||
class: "cleric",
|
||||
level: 5,
|
||||
goldPerSecond: 10,
|
||||
essencePerSecond: 0.05,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "ranger",
|
||||
name: "Ranger",
|
||||
class: "ranger",
|
||||
level: 6,
|
||||
goldPerSecond: 25,
|
||||
essencePerSecond: 0.1,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "knight",
|
||||
name: "Knight",
|
||||
class: "warrior",
|
||||
level: 7,
|
||||
goldPerSecond: 75,
|
||||
essencePerSecond: 0.2,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "archmage",
|
||||
name: "Archmage",
|
||||
class: "mage",
|
||||
level: 8,
|
||||
goldPerSecond: 200,
|
||||
essencePerSecond: 0.5,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "paladin",
|
||||
name: "Paladin",
|
||||
class: "paladin",
|
||||
level: 9,
|
||||
goldPerSecond: 600,
|
||||
essencePerSecond: 1,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "dragon_rider",
|
||||
name: "Dragon Rider",
|
||||
class: "ranger",
|
||||
level: 10,
|
||||
goldPerSecond: 2000,
|
||||
essencePerSecond: 3,
|
||||
count: 0,
|
||||
unlocked: false,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { Boss } from "@elysium/types";
|
||||
|
||||
export const DEFAULT_BOSSES: Boss[] = [
|
||||
{
|
||||
id: "troll_king",
|
||||
name: "The Troll King",
|
||||
description:
|
||||
"Gruk the Immovable has terrorised the trade roads for decades. Merchants will pay handsomely for his head.",
|
||||
status: "available",
|
||||
maxHp: 1_000,
|
||||
currentHp: 1_000,
|
||||
damagePerSecond: 5,
|
||||
goldReward: 10_000,
|
||||
essenceReward: 25,
|
||||
crystalReward: 0,
|
||||
upgradeRewards: ["click_2"],
|
||||
prestigeRequirement: 0,
|
||||
},
|
||||
{
|
||||
id: "lich_queen",
|
||||
name: "The Lich Queen",
|
||||
description:
|
||||
"Seraphina the Undying commands legions of undead from her bone throne. Her defeat will echo through history.",
|
||||
status: "locked",
|
||||
maxHp: 10_000,
|
||||
currentHp: 10_000,
|
||||
damagePerSecond: 20,
|
||||
goldReward: 100_000,
|
||||
essenceReward: 200,
|
||||
crystalReward: 10,
|
||||
upgradeRewards: ["global_2"],
|
||||
prestigeRequirement: 0,
|
||||
},
|
||||
{
|
||||
id: "elder_dragon",
|
||||
name: "Elder Dragon Vaeltharox",
|
||||
description:
|
||||
"The eldest dragon in existence, older than the kingdom itself. Even his breath can level mountains.",
|
||||
status: "locked",
|
||||
maxHp: 100_000,
|
||||
currentHp: 100_000,
|
||||
damagePerSecond: 75,
|
||||
goldReward: 1_000_000,
|
||||
essenceReward: 1_000,
|
||||
crystalReward: 50,
|
||||
upgradeRewards: ["click_3"],
|
||||
prestigeRequirement: 1,
|
||||
},
|
||||
{
|
||||
id: "void_titan",
|
||||
name: "The Void Titan",
|
||||
description:
|
||||
"A creature from beyond the veil of reality, drawn by the power your guild has accumulated. It must not be allowed to exist.",
|
||||
status: "locked",
|
||||
maxHp: 1_000_000,
|
||||
currentHp: 1_000_000,
|
||||
damagePerSecond: 250,
|
||||
goldReward: 10_000_000,
|
||||
essenceReward: 5_000,
|
||||
crystalReward: 200,
|
||||
upgradeRewards: [],
|
||||
prestigeRequirement: 3,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { GameState, Player, PrestigeData } from "@elysium/types";
|
||||
import { DEFAULT_ADVENTURERS } from "./adventurers.js";
|
||||
import { DEFAULT_BOSSES } from "./bosses.js";
|
||||
import { DEFAULT_QUESTS } from "./quests.js";
|
||||
import { DEFAULT_UPGRADES } from "./upgrades.js";
|
||||
|
||||
export const INITIAL_PRESTIGE: PrestigeData = {
|
||||
count: 0,
|
||||
runestones: 0,
|
||||
productionMultiplier: 1,
|
||||
purchasedUpgradeIds: [],
|
||||
};
|
||||
|
||||
export const INITIAL_GAME_STATE = (player: Player, characterName: string): GameState => ({
|
||||
player: {
|
||||
...player,
|
||||
characterName,
|
||||
totalGoldEarned: 0,
|
||||
totalClicks: 0,
|
||||
},
|
||||
resources: {
|
||||
gold: 0,
|
||||
essence: 0,
|
||||
crystals: 0,
|
||||
runestones: 0,
|
||||
},
|
||||
adventurers: structuredClone(DEFAULT_ADVENTURERS),
|
||||
upgrades: structuredClone(DEFAULT_UPGRADES),
|
||||
quests: structuredClone(DEFAULT_QUESTS),
|
||||
bosses: structuredClone(DEFAULT_BOSSES),
|
||||
prestige: INITIAL_PRESTIGE,
|
||||
baseClickPower: 1,
|
||||
lastTickAt: Date.now(),
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { Quest } from "@elysium/types";
|
||||
|
||||
export const DEFAULT_QUESTS: Quest[] = [
|
||||
{
|
||||
id: "first_steps",
|
||||
name: "First Steps",
|
||||
description: "Every legend begins somewhere. Send your first adventurer into the field.",
|
||||
status: "available",
|
||||
durationSeconds: 60,
|
||||
rewards: [{ type: "gold", amount: 500 }],
|
||||
prerequisiteIds: [],
|
||||
},
|
||||
{
|
||||
id: "goblin_camp",
|
||||
name: "Goblin Camp",
|
||||
description: "Clear out a troublesome goblin camp to the east.",
|
||||
status: "locked",
|
||||
durationSeconds: 5 * 60,
|
||||
rewards: [
|
||||
{ type: "gold", amount: 2_000 },
|
||||
{ type: "essence", amount: 5 },
|
||||
],
|
||||
prerequisiteIds: ["first_steps"],
|
||||
},
|
||||
{
|
||||
id: "haunted_mine",
|
||||
name: "The Haunted Mine",
|
||||
description: "An abandoned mine is rich with crystal deposits — if you dare brave its ghosts.",
|
||||
status: "locked",
|
||||
durationSeconds: 15 * 60,
|
||||
rewards: [
|
||||
{ type: "crystals", amount: 10 },
|
||||
{ type: "upgrade", targetId: "global_1" },
|
||||
],
|
||||
prerequisiteIds: ["goblin_camp"],
|
||||
},
|
||||
{
|
||||
id: "ancient_ruins",
|
||||
name: "Ancient Ruins",
|
||||
description: "Scholars believe the ruins hold secrets of a forgotten civilisation.",
|
||||
status: "locked",
|
||||
durationSeconds: 30 * 60,
|
||||
rewards: [
|
||||
{ type: "essence", amount: 50 },
|
||||
{ type: "upgrade", targetId: "click_2" },
|
||||
],
|
||||
prerequisiteIds: ["haunted_mine"],
|
||||
},
|
||||
{
|
||||
id: "dragon_lair",
|
||||
name: "Dragon's Lair",
|
||||
description:
|
||||
"The legendary lair of Pyraxis the Undying. Few who enter return — those who do are rich beyond imagining.",
|
||||
status: "locked",
|
||||
durationSeconds: 60 * 60,
|
||||
rewards: [
|
||||
{ type: "gold", amount: 500_000 },
|
||||
{ type: "crystals", amount: 50 },
|
||||
{ type: "adventurer", targetId: "dragon_rider" },
|
||||
],
|
||||
prerequisiteIds: ["ancient_ruins"],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,98 @@
|
||||
import type { Upgrade } from "@elysium/types";
|
||||
|
||||
export const DEFAULT_UPGRADES: Upgrade[] = [
|
||||
// Click upgrades
|
||||
{
|
||||
id: "click_1",
|
||||
name: "Keen Eye",
|
||||
description: "Your strikes find weak points. Doubles click power.",
|
||||
target: "click",
|
||||
multiplier: 2,
|
||||
costGold: 100,
|
||||
costEssence: 0,
|
||||
purchased: false,
|
||||
unlocked: true,
|
||||
},
|
||||
{
|
||||
id: "click_2",
|
||||
name: "Battle Hardened",
|
||||
description: "Years of combat sharpen your instincts. Doubles click power again.",
|
||||
target: "click",
|
||||
multiplier: 2,
|
||||
costGold: 1000,
|
||||
costEssence: 0,
|
||||
purchased: false,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "click_3",
|
||||
name: "Legendary Weapon",
|
||||
description: "A weapon of ancient power. Triples click power.",
|
||||
target: "click",
|
||||
multiplier: 3,
|
||||
costGold: 50_000,
|
||||
costEssence: 10,
|
||||
purchased: false,
|
||||
unlocked: false,
|
||||
},
|
||||
// Global upgrades
|
||||
{
|
||||
id: "global_1",
|
||||
name: "Guild Charter",
|
||||
description: "Formalising the guild structure increases all income by 25%.",
|
||||
target: "global",
|
||||
multiplier: 1.25,
|
||||
costGold: 500,
|
||||
costEssence: 0,
|
||||
purchased: false,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "global_2",
|
||||
name: "Merchant Alliance",
|
||||
description: "Trade routes boost all income by 50%.",
|
||||
target: "global",
|
||||
multiplier: 1.5,
|
||||
costGold: 10_000,
|
||||
costEssence: 5,
|
||||
purchased: false,
|
||||
unlocked: false,
|
||||
},
|
||||
// Adventurer-specific upgrades
|
||||
{
|
||||
id: "peasant_1",
|
||||
name: "Better Tools",
|
||||
description: "Peasants work twice as hard with proper equipment.",
|
||||
target: "adventurer",
|
||||
adventurerId: "peasant",
|
||||
multiplier: 2,
|
||||
costGold: 200,
|
||||
costEssence: 0,
|
||||
purchased: false,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "militia_1",
|
||||
name: "Militia Training",
|
||||
description: "Formal training doubles militia effectiveness.",
|
||||
target: "adventurer",
|
||||
adventurerId: "militia",
|
||||
multiplier: 2,
|
||||
costGold: 1_000,
|
||||
costEssence: 0,
|
||||
purchased: false,
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: "mage_1",
|
||||
name: "Arcane Tomes",
|
||||
description: "Ancient books of magic double mage output.",
|
||||
target: "adventurer",
|
||||
adventurerId: "apprentice",
|
||||
multiplier: 2,
|
||||
costGold: 5_000,
|
||||
costEssence: 2,
|
||||
purchased: false,
|
||||
unlocked: false,
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user