Add Lightning mana type, AOE spells, room types, and monster armor

Features added:
- Lightning mana type (Fire + Air composite)
- AOE spells (Chain Lightning, Fireball AOE, Blizzard, etc.)
- Magic sword enchantments (Fire Blade, Frost Blade, Lightning Blade)
- Monster armor system (all guardians have armor, scales with floors)
- Room types (puzzle, swarm, speed) with generation logic
- FloorState and EnemyState types for room handling
- Weapon mana storage fields for future magic sword system
This commit is contained in:
Z User
2026-03-30 15:32:40 +00:00
parent 0bc2b45b96
commit dd9528a418
3 changed files with 548 additions and 6 deletions

View File

@@ -39,10 +39,11 @@ export const ELEMENTS: Record<string, ElementDef> = {
force: { name: "Force", sym: "💨", color: "#E74C3C", glow: "#E74C3C40", cat: "utility" },
// Composite Elements
blood: { name: "Blood", sym: "🩸", color: "#C0392B", glow: "#C0392B40", cat: "composite", recipe: ["life", "water"] },
metal: { name: "Metal", sym: "⚙️", color: "#BDC3C7", glow: "#BDC3C740", cat: "composite", recipe: ["fire", "earth"] },
wood: { name: "Wood", sym: "🪵", color: "#8B5E3C", glow: "#8B5E3C40", cat: "composite", recipe: ["life", "earth"] },
sand: { name: "Sand", sym: "⏳", color: "#D4AC0D", glow: "#D4AC0D40", cat: "composite", recipe: ["earth", "water"] },
blood: { name: "Blood", sym: "🩸", color: "#C0392B", glow: "#C0392B40", cat: "composite", recipe: ["life", "water"] },
metal: { name: "Metal", sym: "⚙️", color: "#BDC3C7", glow: "#BDC3C740", cat: "composite", recipe: ["fire", "earth"] },
wood: { name: "Wood", sym: "🪵", color: "#8B5E3C", glow: "#8B5E3C40", cat: "composite", recipe: ["life", "earth"] },
sand: { name: "Sand", sym: "⏳", color: "#D4AC0D", glow: "#D4AC0D40", cat: "composite", recipe: ["earth", "water"] },
lightning: { name: "Lightning", sym: "⚡", color: "#FFEB3B", glow: "#FFEB3B40", cat: "composite", recipe: ["fire", "air"] },
// Exotic Elements
crystal: { name: "Crystal", sym: "💎", color: "#85C1E9", glow: "#85C1E940", cat: "exotic", recipe: ["sand", "sand", "mental"] },
@@ -52,10 +53,103 @@ export const ELEMENTS: Record<string, ElementDef> = {
export const FLOOR_ELEM_CYCLE = ["fire", "water", "air", "earth", "light", "dark", "life", "death"];
// ─── Room Types ────────────────────────────────────────────────────────────────
// Room types for spire floors
export type RoomType = 'combat' | 'puzzle' | 'swarm' | 'speed' | 'guardian';
// Room generation rules:
// - Guardian floors (10, 20, 30, etc.) are ALWAYS guardian type
// - Every 5th floor (5, 15, 25, etc.) has a chance for special rooms
// - Other floors are combat with chance for swarm/speed
export const PUZZLE_ROOM_INTERVAL = 7; // Every 7 floors, chance for puzzle
export const SWARM_ROOM_CHANCE = 0.15; // 15% chance for swarm room
export const SPEED_ROOM_CHANCE = 0.10; // 10% chance for speed room
export const PUZZLE_ROOM_CHANCE = 0.20; // 20% chance for puzzle room on puzzle floors
// Puzzle room definitions - themed around attunements
export const PUZZLE_ROOMS: Record<string, {
name: string;
attunements: string[]; // Which attunements speed up progress
baseProgressPerTick: number; // Base progress rate
attunementBonus: number; // Multiplier per relevant attunement level
description: string;
}> = {
enchanter_trial: {
name: "Enchanter's Trial",
attunements: ['enchanter'],
baseProgressPerTick: 0.02,
attunementBonus: 0.03,
description: "Decipher ancient enchantment runes."
},
fabricator_trial: {
name: "Fabricator's Trial",
attunements: ['fabricator'],
baseProgressPerTick: 0.02,
attunementBonus: 0.03,
description: "Construct a mana-powered mechanism."
},
invoker_trial: {
name: "Invoker's Trial",
attunements: ['invoker'],
baseProgressPerTick: 0.02,
attunementBonus: 0.03,
description: "Commune with guardian spirits."
},
hybrid_enchanter_fabricator: {
name: "Fusion Workshop",
attunements: ['enchanter', 'fabricator'],
baseProgressPerTick: 0.015,
attunementBonus: 0.025,
description: "Enchant and construct in harmony."
},
hybrid_enchanter_invoker: {
name: "Ritual Circle",
attunements: ['enchanter', 'invoker'],
baseProgressPerTick: 0.015,
attunementBonus: 0.025,
description: "Bind pact energies into enchantments."
},
hybrid_fabricator_invoker: {
name: "Golem Forge",
attunements: ['fabricator', 'invoker'],
baseProgressPerTick: 0.015,
attunementBonus: 0.025,
description: "Channel guardian power into constructs."
},
};
// Swarm room configuration
export const SWARM_CONFIG = {
minEnemies: 3,
maxEnemies: 6,
hpMultiplier: 0.4, // Each enemy has 40% of normal floor HP
armorBase: 0, // Swarm enemies start with no armor
armorPerFloor: 0.01, // Gain 1% armor per 10 floors
};
// Speed room configuration (dodging enemies)
export const SPEED_ROOM_CONFIG = {
baseDodgeChance: 0.25, // 25% base dodge chance
dodgePerFloor: 0.005, // +0.5% dodge per floor
maxDodge: 0.50, // Max 50% dodge
speedBonus: 0.5, // 50% less time to complete if dodged
};
// Armor scaling for normal floors
export const FLOOR_ARMOR_CONFIG = {
baseChance: 0, // No armor on floor 1-9
chancePerFloor: 0.01, // +1% chance per floor after 10
maxArmorChance: 0.5, // Max 50% of floors have armor
minArmor: 0.05, // Min 5% armor
maxArmor: 0.25, // Max 25% armor on non-guardians
};
// ─── Guardians ────────────────────────────────────────────────────────────────
// All guardians have armor - damage reduction percentage
export const GUARDIANS: Record<number, GuardianDef> = {
10: {
name: "Ignis Prime", element: "fire", hp: 5000, pact: 1.5, color: "#FF6B35",
armor: 0.10, // 10% damage reduction
boons: [
{ type: 'elementalDamage', value: 5, desc: '+5% Fire damage' },
{ type: 'maxMana', value: 50, desc: '+50 max mana' },
@@ -66,6 +160,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
20: {
name: "Aqua Regia", element: "water", hp: 15000, pact: 1.75, color: "#4ECDC4",
armor: 0.15,
boons: [
{ type: 'elementalDamage', value: 5, desc: '+5% Water damage' },
{ type: 'manaRegen', value: 0.5, desc: '+0.5 mana regen' },
@@ -76,6 +171,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
30: {
name: "Ventus Rex", element: "air", hp: 30000, pact: 2.0, color: "#00D4FF",
armor: 0.18,
boons: [
{ type: 'elementalDamage', value: 5, desc: '+5% Air damage' },
{ type: 'castingSpeed', value: 5, desc: '+5% cast speed' },
@@ -86,6 +182,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
40: {
name: "Terra Firma", element: "earth", hp: 50000, pact: 2.25, color: "#F4A261",
armor: 0.25, // Earth guardian - highest armor
boons: [
{ type: 'elementalDamage', value: 5, desc: '+5% Earth damage' },
{ type: 'maxMana', value: 100, desc: '+100 max mana' },
@@ -96,6 +193,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
50: {
name: "Lux Aeterna", element: "light", hp: 80000, pact: 2.5, color: "#FFD700",
armor: 0.20,
boons: [
{ type: 'elementalDamage', value: 10, desc: '+10% Light damage' },
{ type: 'insightGain', value: 10, desc: '+10% insight gain' },
@@ -106,6 +204,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
60: {
name: "Umbra Mortis", element: "dark", hp: 120000, pact: 2.75, color: "#9B59B6",
armor: 0.22,
boons: [
{ type: 'elementalDamage', value: 10, desc: '+10% Dark damage' },
{ type: 'critDamage', value: 15, desc: '+15% crit damage' },
@@ -116,6 +215,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
70: {
name: "Vita Sempiterna", element: "life", hp: 180000, pact: 3.0, color: "#2ECC71",
armor: 0.20,
boons: [
{ type: 'elementalDamage', value: 10, desc: '+10% Life damage' },
{ type: 'manaRegen', value: 1, desc: '+1 mana regen' },
@@ -126,6 +226,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
80: {
name: "Mors Ultima", element: "death", hp: 250000, pact: 3.25, color: "#778CA3",
armor: 0.25,
boons: [
{ type: 'elementalDamage', value: 10, desc: '+10% Death damage' },
{ type: 'rawDamage', value: 10, desc: '+10% raw damage' },
@@ -136,6 +237,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
90: {
name: "Primordialis", element: "void", hp: 400000, pact: 4.0, color: "#4A235A",
armor: 0.30,
boons: [
{ type: 'elementalDamage', value: 15, desc: '+15% Void damage' },
{ type: 'maxMana', value: 200, desc: '+200 max mana' },
@@ -147,6 +249,7 @@ export const GUARDIANS: Record<number, GuardianDef> = {
},
100: {
name: "The Awakened One", element: "stellar", hp: 1000000, pact: 5.0, color: "#F0E68C",
armor: 0.35, // Final boss has highest armor
boons: [
{ type: 'elementalDamage', value: 20, desc: '+20% Stellar damage' },
{ type: 'maxMana', value: 500, desc: '+500 max mana' },
@@ -648,6 +751,228 @@ export const SPELLS_DEF: Record<string, SpellDef> = {
studyTime: 36,
desc: "Shatter crystalline energy."
},
// ═══════════════════════════════════════════════════════════════════════════
// LIGHTNING SPELLS - Fast, armor-piercing, harder to dodge
// ═══════════════════════════════════════════════════════════════════════════
// Tier 1 - Basic Lightning
spark: {
name: "Spark",
elem: "lightning",
dmg: 8,
cost: elemCost("lightning", 1),
tier: 1,
castSpeed: 4,
unlock: 120,
studyTime: 2,
desc: "A quick spark of lightning. Very fast and hard to dodge.",
effects: [{ type: 'armor_pierce', value: 0.2 }]
},
lightningBolt: {
name: "Lightning Bolt",
elem: "lightning",
dmg: 14,
cost: elemCost("lightning", 2),
tier: 1,
castSpeed: 3,
unlock: 150,
studyTime: 3,
desc: "A bolt of lightning that pierces armor.",
effects: [{ type: 'armor_pierce', value: 0.3 }]
},
// Tier 2 - Advanced Lightning
chainLightning: {
name: "Chain Lightning",
elem: "lightning",
dmg: 25,
cost: elemCost("lightning", 5),
tier: 2,
castSpeed: 2,
unlock: 900,
studyTime: 8,
desc: "Lightning that arcs between enemies. Hits 3 targets.",
isAoe: true,
aoeTargets: 3,
effects: [{ type: 'chain', value: 3 }]
},
stormCall: {
name: "Storm Call",
elem: "lightning",
dmg: 40,
cost: elemCost("lightning", 6),
tier: 2,
castSpeed: 1.5,
unlock: 1100,
studyTime: 10,
desc: "Call down a storm. Hits 2 targets with armor pierce.",
isAoe: true,
aoeTargets: 2,
effects: [{ type: 'armor_pierce', value: 0.4 }]
},
// Tier 3 - Master Lightning
thunderStrike: {
name: "Thunder Strike",
elem: "lightning",
dmg: 150,
cost: elemCost("lightning", 15),
tier: 3,
castSpeed: 0.8,
unlock: 10000,
studyTime: 24,
desc: "Devastating lightning that ignores 50% armor.",
effects: [{ type: 'armor_pierce', value: 0.5 }]
},
// ═══════════════════════════════════════════════════════════════════════════
// AOE SPELLS - Hit multiple enemies, less damage per target
// ═══════════════════════════════════════════════════════════════════════════
// Tier 1 AOE
fireballAoe: {
name: "Fireball (AOE)",
elem: "fire",
dmg: 8,
cost: elemCost("fire", 3),
tier: 1,
castSpeed: 2,
unlock: 150,
studyTime: 3,
desc: "An explosive fireball that hits 3 enemies.",
isAoe: true,
aoeTargets: 3,
effects: [{ type: 'aoe', value: 3 }]
},
frostNova: {
name: "Frost Nova",
elem: "water",
dmg: 6,
cost: elemCost("water", 3),
tier: 1,
castSpeed: 2,
unlock: 140,
studyTime: 3,
desc: "A burst of frost hitting 4 enemies. May freeze.",
isAoe: true,
aoeTargets: 4,
effects: [{ type: 'freeze', value: 0.15, chance: 0.2 }]
},
// Tier 2 AOE
meteorShower: {
name: "Meteor Shower",
elem: "fire",
dmg: 20,
cost: elemCost("fire", 8),
tier: 2,
castSpeed: 1,
unlock: 1200,
studyTime: 10,
desc: "Rain meteors on 5 enemies.",
isAoe: true,
aoeTargets: 5
},
blizzard: {
name: "Blizzard",
elem: "water",
dmg: 18,
cost: elemCost("water", 7),
tier: 2,
castSpeed: 1.2,
unlock: 1000,
studyTime: 9,
desc: "A freezing blizzard hitting 4 enemies.",
isAoe: true,
aoeTargets: 4,
effects: [{ type: 'freeze', value: 0.1, chance: 0.15 }]
},
earthquakeAoe: {
name: "Earth Tremor",
elem: "earth",
dmg: 25,
cost: elemCost("earth", 8),
tier: 2,
castSpeed: 0.8,
unlock: 1400,
studyTime: 10,
desc: "Shake the ground, hitting 3 enemies with high damage.",
isAoe: true,
aoeTargets: 3
},
// Tier 3 AOE
apocalypse: {
name: "Apocalypse",
elem: "fire",
dmg: 80,
cost: elemCost("fire", 20),
tier: 3,
castSpeed: 0.5,
unlock: 15000,
studyTime: 30,
desc: "End times. Hits ALL enemies with devastating fire.",
isAoe: true,
aoeTargets: 10
},
// ═══════════════════════════════════════════════════════════════════════════
// MAGIC SWORD ENCHANTMENTS - For weapon enchanting system
// ═══════════════════════════════════════════════════════════════════════════
fireBlade: {
name: "Fire Blade",
elem: "fire",
dmg: 3,
cost: rawCost(1),
tier: 1,
castSpeed: 4,
unlock: 100,
studyTime: 2,
desc: "Enchant a blade with fire. Burns enemies over time.",
isWeaponEnchant: true,
effects: [{ type: 'burn', value: 2, duration: 3 }]
},
frostBlade: {
name: "Frost Blade",
elem: "water",
dmg: 3,
cost: rawCost(1),
tier: 1,
castSpeed: 4,
unlock: 100,
studyTime: 2,
desc: "Enchant a blade with frost. Prevents enemy dodge.",
isWeaponEnchant: true,
effects: [{ type: 'freeze', value: 0, chance: 1 }] // 100% freeze = no dodge
},
lightningBlade: {
name: "Lightning Blade",
elem: "lightning",
dmg: 4,
cost: rawCost(1),
tier: 1,
castSpeed: 5,
unlock: 150,
studyTime: 3,
desc: "Enchant a blade with lightning. Pierces 30% armor.",
isWeaponEnchant: true,
effects: [{ type: 'armor_pierce', value: 0.3 }]
},
voidBlade: {
name: "Void Blade",
elem: "dark",
dmg: 5,
cost: rawCost(2),
tier: 2,
castSpeed: 3,
unlock: 800,
studyTime: 8,
desc: "Enchant a blade with void. 10% lifesteal.",
isWeaponEnchant: true,
effects: [{ type: 'lifesteal', value: 0.1 }]
},
};
// ─── Skills ───────────────────────────────────────────────────────────────────
@@ -848,6 +1173,7 @@ export const ELEMENT_OPPOSITES: Record<string, string> = {
air: 'earth', earth: 'air',
light: 'dark', dark: 'light',
life: 'death', death: 'life',
lightning: 'earth', // Lightning is weak to earth (grounding)
};
// ─── Element Icon Mapping (Lucide Icons) ──────────────────────────────────────
@@ -869,6 +1195,7 @@ export const ELEMENT_ICON_NAMES: Record<string, string> = {
metal: 'Target',
wood: 'TreeDeciduous',
sand: 'Hourglass',
lightning: 'Zap',
crystal: 'Gem',
stellar: 'Star',
void: 'CircleDot',

View File

@@ -2,7 +2,7 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { GameState, GameAction, StudyTarget, SpellCost, SkillUpgradeChoice, EquipmentSlot, EquipmentInstance, EnchantmentDesign, DesignEffect, AttunementState } from './types';
import type { GameState, GameAction, StudyTarget, SpellCost, SkillUpgradeChoice, EquipmentSlot, EquipmentInstance, EnchantmentDesign, DesignEffect, AttunementState, FloorState, EnemyState, RoomType } from './types';
import {
ELEMENTS,
GUARDIANS,
@@ -22,6 +22,14 @@ import {
EFFECT_RESEARCH_MAPPING,
BASE_UNLOCKED_EFFECTS,
ENCHANTING_UNLOCK_EFFECTS,
PUZZLE_ROOMS,
PUZZLE_ROOM_INTERVAL,
PUZZLE_ROOM_CHANCE,
SWARM_ROOM_CHANCE,
SPEED_ROOM_CHANCE,
SWARM_CONFIG,
SPEED_ROOM_CONFIG,
FLOOR_ARMOR_CONFIG,
} from './constants';
import { computeEffects, hasSpecial, SPECIAL_EFFECTS, type ComputedEffects } from './upgrade-effects';
import {
@@ -99,6 +107,174 @@ export function getFloorElement(floor: number): string {
return FLOOR_ELEM_CYCLE[(floor - 1) % 8];
}
// ─── Room Generation Functions ────────────────────────────────────────────────
// Generate room type for a floor
export function generateRoomType(floor: number): RoomType {
// Guardian floors are always guardian type
if (GUARDIANS[floor]) {
return 'guardian';
}
// Check for puzzle room (every PUZZLE_ROOM_INTERVAL floors)
if (floor % PUZZLE_ROOM_INTERVAL === 0 && Math.random() < PUZZLE_ROOM_CHANCE) {
return 'puzzle';
}
// Check for swarm room
if (Math.random() < SWARM_ROOM_CHANCE) {
return 'swarm';
}
// Check for speed room
if (Math.random() < SPEED_ROOM_CHANCE) {
return 'speed';
}
// Default to combat
return 'combat';
}
// Get armor for a non-guardian floor
export function getFloorArmor(floor: number): number {
if (GUARDIANS[floor]) {
return GUARDIANS[floor].armor || 0;
}
// Armor becomes more common on higher floors
if (floor < 10) return 0;
const armorChance = Math.min(FLOOR_ARMOR_CONFIG.maxArmorChance,
FLOOR_ARMOR_CONFIG.baseChance + (floor - 10) * FLOOR_ARMOR_CONFIG.chancePerFloor);
if (Math.random() > armorChance) return 0;
// Scale armor with floor
const armorRange = FLOOR_ARMOR_CONFIG.maxArmor - FLOOR_ARMOR_CONFIG.minArmor;
const floorProgress = Math.min(1, (floor - 10) / 90);
return FLOOR_ARMOR_CONFIG.minArmor + armorRange * floorProgress * Math.random();
}
// Get dodge chance for a speed room
export function getDodgeChance(floor: number): number {
return Math.min(
SPEED_ROOM_CONFIG.maxDodge,
SPEED_ROOM_CONFIG.baseDodgeChance + floor * SPEED_ROOM_CONFIG.dodgePerFloor
);
}
// Generate enemies for a swarm room
export function generateSwarmEnemies(floor: number): EnemyState[] {
const baseHP = getFloorMaxHP(floor);
const element = getFloorElement(floor);
const numEnemies = SWARM_CONFIG.minEnemies +
Math.floor(Math.random() * (SWARM_CONFIG.maxEnemies - SWARM_CONFIG.minEnemies + 1));
const enemies: EnemyState[] = [];
for (let i = 0; i < numEnemies; i++) {
enemies.push({
id: `enemy_${i}`,
hp: Math.floor(baseHP * SWARM_CONFIG.hpMultiplier),
maxHP: Math.floor(baseHP * SWARM_CONFIG.hpMultiplier),
armor: SWARM_CONFIG.armorBase + Math.floor(floor / 10) * SWARM_CONFIG.armorPerFloor,
dodgeChance: 0,
element,
});
}
return enemies;
}
// Generate initial floor state
export function generateFloorState(floor: number): FloorState {
const roomType = generateRoomType(floor);
const element = getFloorElement(floor);
const baseHP = getFloorMaxHP(floor);
const guardian = GUARDIANS[floor];
switch (roomType) {
case 'guardian':
return {
roomType: 'guardian',
enemies: [{
id: 'guardian',
hp: guardian.hp,
maxHP: guardian.hp,
armor: guardian.armor || 0,
dodgeChance: 0,
element: guardian.element,
}],
};
case 'swarm':
return {
roomType: 'swarm',
enemies: generateSwarmEnemies(floor),
};
case 'speed':
return {
roomType: 'speed',
enemies: [{
id: 'speed_enemy',
hp: baseHP,
maxHP: baseHP,
armor: getFloorArmor(floor),
dodgeChance: getDodgeChance(floor),
element,
}],
};
case 'puzzle': {
// Select a puzzle type based on player's attunements
const puzzleKeys = Object.keys(PUZZLE_ROOMS);
const selectedPuzzle = puzzleKeys[Math.floor(Math.random() * puzzleKeys.length)];
const puzzle = PUZZLE_ROOMS[selectedPuzzle];
return {
roomType: 'puzzle',
enemies: [],
puzzleProgress: 0,
puzzleRequired: 1,
puzzleId: selectedPuzzle,
puzzleAttunements: puzzle.attunements,
};
}
default: // combat
return {
roomType: 'combat',
enemies: [{
id: 'enemy',
hp: baseHP,
maxHP: baseHP,
armor: getFloorArmor(floor),
dodgeChance: 0,
element,
}],
};
}
}
// Get puzzle progress speed based on attunements
export function getPuzzleProgressSpeed(
puzzleId: string,
attunements: Record<string, AttunementState>
): number {
const puzzle = PUZZLE_ROOMS[puzzleId];
if (!puzzle) return 0.02; // Default slow progress
let speed = puzzle.baseProgressPerTick;
// Add bonus for each relevant attunement level
for (const attId of puzzle.attunements) {
const attState = attunements[attId];
if (attState?.active) {
speed += puzzle.attunementBonus * (attState.level || 1);
}
}
return speed;
}
// ─── Computed Stats Functions ─────────────────────────────────────────────────
// Helper to get effective skill level accounting for tiers
@@ -467,6 +643,9 @@ function makeInitial(overrides: Partial<GameState> = {}): GameState {
currentAction: 'meditate',
castProgress: 0,
// Initialize room state
currentRoom: generateFloorState(startFloor),
spells: startSpells,
skills: overrides.skills || {},
skillProgress: {},

View File

@@ -64,6 +64,7 @@ export interface GuardianDef {
pactCost: number; // Mana cost to perform pact ritual
pactTime: number; // Hours required for pact ritual
uniquePerk: string; // Description of unique perk
armor?: number; // Damage reduction (0-1, e.g., 0.2 = 20% reduction)
}
// Spell cost can be raw mana or elemental mana
@@ -84,12 +85,17 @@ export interface SpellDef {
castSpeed?: number; // Casts per hour (default 1, higher = faster)
desc?: string; // Optional spell description
effects?: SpellEffect[]; // Optional special effects
isAoe?: boolean; // AOE spell that hits multiple enemies
aoeTargets?: number; // Number of enemies hit by AOE
isWeaponEnchant?: boolean; // Can be used as weapon enchantment (magic swords)
}
export interface SpellEffect {
type: 'lifesteal' | 'burn' | 'freeze' | 'stun' | 'pierce' | 'multicast' | 'shield' | 'buff';
type: 'lifesteal' | 'burn' | 'freeze' | 'stun' | 'pierce' | 'multicast' | 'shield' | 'buff' | 'chain' | 'aoe' | 'armor_pierce';
value: number; // Effect potency
duration?: number; // Duration in hours for timed effects
targets?: number; // For AOE: number of targets
chance?: number; // For chance-based effects (e.g., stun chance)
}
export interface SpellState {
@@ -98,6 +104,28 @@ export interface SpellState {
studyProgress?: number; // Hours studied so far (for in-progress spells)
}
// ─── Room and Enemy Types ─────────────────────────────────────────────────────
export type RoomType = 'combat' | 'puzzle' | 'swarm' | 'speed' | 'guardian';
export interface EnemyState {
id: string;
hp: number;
maxHP: number;
armor: number; // Damage reduction (0-1)
dodgeChance: number; // For speed rooms (0-1)
element: string;
}
export interface FloorState {
roomType: RoomType;
enemies: EnemyState[]; // For swarm rooms, multiple enemies
puzzleProgress?: number; // For puzzle rooms (0-1)
puzzleRequired?: number; // Total progress needed
puzzleId?: string; // Which puzzle type
puzzleAttunements?: string[]; // Which attunements speed up this puzzle
}
export interface SkillDef {
name: string;
desc: string;
@@ -183,6 +211,11 @@ export interface EquipmentInstance {
totalCapacity: number; // Base capacity + bonuses
rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary' | 'mythic';
quality: number; // 0-100, affects capacity efficiency
weaponMana?: number; // Current mana stored in weapon (for weapon enchantments)
weaponManaMax?: number; // Max mana the weapon can store
weaponManaRegen?: number; // Mana regen per hour for weapon
weaponManaType?: string; // Type of mana the weapon stores
activeWeaponEnchant?: string; // Active weapon enchantment (for magic swords)
}
export interface AppliedEnchantment {
@@ -347,6 +380,9 @@ export interface GameState {
currentAction: GameAction;
castProgress: number; // Progress towards next spell cast (0-1)
// Room system for special floors
currentRoom: FloorState; // Current room state (swarm, puzzle, speed, etc.)
// Spells
spells: Record<string, SpellState>;