feature: add new composite and exotic mana types (ticket #202)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 17s

This commit is contained in:
2026-05-29 21:51:45 +02:00
parent 7bd28e2085
commit e3ce18c601
31 changed files with 1279 additions and 170 deletions
@@ -108,6 +108,66 @@ export const elementalRegenAdvancedDisciplines: DisciplineDefinition[] = [
drainBase: 2,
sourceManaTypes: ['raw', 'fire', 'air'],
}),
createAdvancedConversionDiscipline({
id: 'regen-frost',
name: 'Frost',
manaType: 'frost',
cost: 12,
description: 'Convert raw mana + air mana + water mana into frost mana over time.',
conversionRate: 0.35,
difficultyFactor: 160,
scalingFactor: 80,
drainBase: 2,
sourceManaTypes: ['raw', 'air', 'water'],
}),
createAdvancedConversionDiscipline({
id: 'regen-blackflame',
name: 'BlackFlame',
manaType: 'blackflame',
cost: 14,
description: 'Convert raw mana + dark mana + fire mana into blackflame mana over time.',
conversionRate: 0.3,
difficultyFactor: 170,
scalingFactor: 85,
drainBase: 2,
sourceManaTypes: ['raw', 'dark', 'fire'],
}),
createAdvancedConversionDiscipline({
id: 'regen-radiantflames',
name: 'Radiant Flames',
manaType: 'radiantflames',
cost: 14,
description: 'Convert raw mana + light mana + fire mana into radiant flames mana over time.',
conversionRate: 0.3,
difficultyFactor: 170,
scalingFactor: 85,
drainBase: 2,
sourceManaTypes: ['raw', 'light', 'fire'],
}),
createAdvancedConversionDiscipline({
id: 'regen-miasma',
name: 'Miasma',
manaType: 'miasma',
cost: 14,
description: 'Convert raw mana + air mana + death mana into miasma mana over time.',
conversionRate: 0.3,
difficultyFactor: 170,
scalingFactor: 85,
drainBase: 2,
sourceManaTypes: ['raw', 'air', 'death'],
}),
createAdvancedConversionDiscipline({
id: 'regen-shadowglass',
name: 'Shadow Glass',
manaType: 'shadowglass',
cost: 15,
description: 'Convert raw mana + earth mana + dark mana into shadow glass mana over time.',
conversionRate: 0.3,
difficultyFactor: 175,
scalingFactor: 88,
drainBase: 2,
sourceManaTypes: ['raw', 'earth', 'dark'],
}),
// ── Exotic Elements ────────────────────────────────────────────────────────
createAdvancedConversionDiscipline({
@@ -127,13 +187,13 @@ export const elementalRegenAdvancedDisciplines: DisciplineDefinition[] = [
id: 'regen-stellar',
name: 'Stellar',
manaType: 'stellar',
cost: 18,
description: 'Convert raw mana + fire mana + light mana into stellar mana over time.',
conversionRate: 0.25,
difficultyFactor: 220,
scalingFactor: 110,
cost: 20,
description: 'Convert raw mana + plasma mana + light mana into stellar mana over time.',
conversionRate: 0.2,
difficultyFactor: 230,
scalingFactor: 115,
drainBase: 3,
sourceManaTypes: ['raw', 'fire', 'light'],
sourceManaTypes: ['raw', 'plasma', 'light'],
infiniteThreshold: 500,
}),
createAdvancedConversionDiscipline({
@@ -149,4 +209,43 @@ export const elementalRegenAdvancedDisciplines: DisciplineDefinition[] = [
sourceManaTypes: ['raw', 'dark', 'death'],
infiniteThreshold: 500,
}),
createAdvancedConversionDiscipline({
id: 'regen-soul',
name: 'Soul',
manaType: 'soul',
cost: 20,
description: 'Convert raw mana + light mana + dark mana + transference mana into soul mana over time.',
conversionRate: 0.2,
difficultyFactor: 240,
scalingFactor: 120,
drainBase: 3,
sourceManaTypes: ['raw', 'light', 'dark', 'transference'],
infiniteThreshold: 550,
}),
createAdvancedConversionDiscipline({
id: 'regen-plasma',
name: 'Plasma',
manaType: 'plasma',
cost: 20,
description: 'Convert raw mana + lightning mana + fire mana + transference mana into plasma mana over time.',
conversionRate: 0.2,
difficultyFactor: 240,
scalingFactor: 120,
drainBase: 3,
sourceManaTypes: ['raw', 'lightning', 'fire', 'transference'],
infiniteThreshold: 550,
}),
createAdvancedConversionDiscipline({
id: 'regen-time',
name: 'Time',
manaType: 'time',
cost: 22,
description: 'Convert raw mana + soul mana + sand mana + transference mana into time mana over time.',
conversionRate: 0.15,
difficultyFactor: 260,
scalingFactor: 130,
drainBase: 3,
sourceManaTypes: ['raw', 'soul', 'sand', 'transference'],
infiniteThreshold: 600,
}),
];
+11 -3
View File
@@ -56,14 +56,22 @@ const MANA_CAPACITY_CONFIGS: ManaCapacityConfig[] = [
{ id: 'attune-transference', name: 'Transference', manaType: 'transference', cost: 8, baseValue: 5, difficultyFactor: 120, scalingFactor: 60, drainBase: 1.5 },
// ── Composite Elements ─────────────────────────────────────────────────────
{ id: 'attune-metal', name: 'Metal', manaType: 'metal', cost: 15, baseValue: 4, difficultyFactor: 180, scalingFactor: 90, drainBase: 2.5 },
{ id: 'attune-sand', name: 'Sand', manaType: 'sand', cost: 15, baseValue: 4, difficultyFactor: 180, scalingFactor: 90, drainBase: 2.5 },
{ id: 'attune-lightning', name: 'Lightning', manaType: 'lightning', cost: 15, baseValue: 4, difficultyFactor: 180, scalingFactor: 90, drainBase: 2.5 },
{ id: 'attune-metal', name: 'Metal', manaType: 'metal', cost: 15, baseValue: 4, difficultyFactor: 180, scalingFactor: 90, drainBase: 2.5 },
{ id: 'attune-sand', name: 'Sand', manaType: 'sand', cost: 15, baseValue: 4, difficultyFactor: 180, scalingFactor: 90, drainBase: 2.5 },
{ id: 'attune-lightning', name: 'Lightning', manaType: 'lightning', cost: 15, baseValue: 4, difficultyFactor: 180, scalingFactor: 90, drainBase: 2.5 },
{ id: 'attune-frost', name: 'Frost', manaType: 'frost', cost: 15, baseValue: 4, difficultyFactor: 180, scalingFactor: 90, drainBase: 2.5 },
{ id: 'attune-blackflame', name: 'BlackFlame', manaType: 'blackflame', cost: 16, baseValue: 4, difficultyFactor: 190, scalingFactor: 95, drainBase: 2.5 },
{ id: 'attune-radiantflames', name: 'Radiant Flames', manaType: 'radiantflames', cost: 16, baseValue: 4, difficultyFactor: 190, scalingFactor: 95, drainBase: 2.5 },
{ id: 'attune-miasma', name: 'Miasma', manaType: 'miasma', cost: 16, baseValue: 4, difficultyFactor: 190, scalingFactor: 95, drainBase: 2.5 },
{ id: 'attune-shadowglass', name: 'Shadow Glass', manaType: 'shadowglass', cost: 17, baseValue: 4, difficultyFactor: 200, scalingFactor: 100, drainBase: 2.5 },
// ── Exotic Elements ────────────────────────────────────────────────────────
{ id: 'attune-crystal', name: 'Crystal', manaType: 'crystal', cost: 20, baseValue: 3, difficultyFactor: 240, scalingFactor: 120, drainBase: 3 },
{ id: 'attune-stellar', name: 'Stellar', manaType: 'stellar', cost: 20, baseValue: 3, difficultyFactor: 240, scalingFactor: 120, drainBase: 3 },
{ id: 'attune-void', name: 'Void', manaType: 'void', cost: 22, baseValue: 3, difficultyFactor: 260, scalingFactor: 130, drainBase: 3.5 },
{ id: 'attune-soul', name: 'Soul', manaType: 'soul', cost: 22, baseValue: 3, difficultyFactor: 260, scalingFactor: 130, drainBase: 3.5 },
{ id: 'attune-time', name: 'Time', manaType: 'time', cost: 24, baseValue: 3, difficultyFactor: 280, scalingFactor: 140, drainBase: 4 },
{ id: 'attune-plasma', name: 'Plasma', manaType: 'plasma', cost: 22, baseValue: 3, difficultyFactor: 250, scalingFactor: 125, drainBase: 3.5 },
];
export const elementalAttunementDisciplines: DisciplineDefinition[] =
@@ -0,0 +1,58 @@
// ─── BlackFlame Spell Effects ──────────────────────────────────
// BlackFlame spells - Dark + Fire compound, curse/DoT focus
import type { EnchantmentEffectDef } from './types';
import { ALL_CASTER } from './types';
export const BLACKFLAME_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_blackFire: {
id: 'spell_blackFire',
name: 'Black Fire',
description: 'Grants the ability to cast Black Fire (12 blackflame damage, burn+curse)',
category: 'spell',
baseCapacityCost: 82,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'blackFire' }
},
spell_shadowEmber: {
id: 'spell_shadowEmber',
name: 'Shadow Ember',
description: 'Grants the ability to cast Shadow Ember (20 blackflame damage, curse)',
category: 'spell',
baseCapacityCost: 105,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'shadowEmber' }
},
spell_darkInferno: {
id: 'spell_darkInferno',
name: 'Dark Inferno',
description: 'Grants the ability to cast Dark Inferno (38 blackflame damage, burn+curse)',
category: 'spell',
baseCapacityCost: 175,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'darkInferno' }
},
spell_umbralBlaze: {
id: 'spell_umbralBlaze',
name: 'Umbral Blaze',
description: 'Grants the ability to cast Umbral Blaze (55 blackflame damage, curse+burn)',
category: 'spell',
baseCapacityCost: 210,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'umbralBlaze' }
},
spell_hellfireCurse: {
id: 'spell_hellfireCurse',
name: 'Hellfire Curse',
description: 'Grants the ability to cast Hellfire Curse (140 blackflame damage, burn+curse)',
category: 'spell',
baseCapacityCost: 410,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'hellfireCurse' }
},
};
@@ -0,0 +1,74 @@
// ─── New Exotic Spell Effects ──────────────────────────────────
// Soul, Time, Plasma spells - Tier 4 exotic elements
import type { EnchantmentEffectDef } from './types';
import { ALL_CASTER } from './types';
export const SOUL_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_soulPierce: {
id: 'spell_soulPierce',
name: 'Soul Pierce',
description: 'Grants the ability to cast Soul Pierce (350 soul damage, defense bypass)',
category: 'spell',
baseCapacityCost: 500,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'soulPierce' }
},
spell_spiritBlast: {
id: 'spell_spiritBlast',
name: 'Spirit Blast',
description: 'Grants the ability to cast Spirit Blast (550 soul damage, full defense bypass)',
category: 'spell',
baseCapacityCost: 650,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'spiritBlast' }
},
};
export const TIME_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_temporalWarp: {
id: 'spell_temporalWarp',
name: 'Temporal Warp',
description: 'Grants the ability to cast Temporal Warp (280 time damage, slow+dodge reduction)',
category: 'spell',
baseCapacityCost: 520,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'temporalWarp' }
},
spell_chronoStasis: {
id: 'spell_chronoStasis',
name: 'Chrono Stasis',
description: 'Grants the ability to cast Chrono Stasis (500 time damage, mage lock)',
category: 'spell',
baseCapacityCost: 680,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'chronoStasis' }
},
};
export const PLASMA_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_plasmaBolt: {
id: 'spell_plasmaBolt',
name: 'Plasma Bolt',
description: 'Grants the ability to cast Plasma Bolt (320 plasma damage, raw damage)',
category: 'spell',
baseCapacityCost: 510,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'plasmaBolt' }
},
spell_plasmaStorm: {
id: 'spell_plasmaStorm',
name: 'Plasma Storm',
description: 'Grants the ability to cast Plasma Storm (600 plasma damage, AoE raw damage)',
category: 'spell',
baseCapacityCost: 660,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'plasmaStorm' }
},
};
@@ -0,0 +1,58 @@
// ─── Frost Spell Effects ──────────────────────────────────────
// Frost spells - Air + Water compound, freeze/slow focus
import type { EnchantmentEffectDef } from './types';
import { ALL_CASTER } from './types';
export const FROST_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_frostBite: {
id: 'spell_frostBite',
name: 'Frost Bite',
description: 'Grants the ability to cast Frost Bite (10 frost damage, freeze)',
category: 'spell',
baseCapacityCost: 78,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'frostBite' }
},
spell_iceShard: {
id: 'spell_iceShard',
name: 'Ice Shard',
description: 'Grants the ability to cast Ice Shard (18 frost damage, freeze)',
category: 'spell',
baseCapacityCost: 95,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'iceShard' }
},
spell_frostNova: {
id: 'spell_frostNova',
name: 'Frost Nova',
description: 'Grants the ability to cast Frost Nova (30 frost damage, AoE slow+freeze)',
category: 'spell',
baseCapacityCost: 165,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'frostNova' }
},
spell_glacialSpike: {
id: 'spell_glacialSpike',
name: 'Glacial Spike',
description: 'Grants the ability to cast Glacial Spike (45 frost damage, freeze)',
category: 'spell',
baseCapacityCost: 200,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'glacialSpike' }
},
spell_absoluteZero: {
id: 'spell_absoluteZero',
name: 'Absolute Zero',
description: 'Grants the ability to cast Absolute Zero (120 frost damage, AoE freeze+slow)',
category: 'spell',
baseCapacityCost: 380,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'absoluteZero' }
},
};
@@ -13,6 +13,12 @@ import { SAND_SPELL_EFFECTS } from './sand-spells';
import { TIER2_SPELL_EFFECTS } from './tier2-spells';
import { TIER3_SPELL_EFFECTS } from './tier3-spells';
import { LEGENDARY_SPELL_EFFECTS } from './legendary-spells';
import { FROST_SPELL_EFFECTS } from './frost-spells';
import { BLACKFLAME_SPELL_EFFECTS } from './blackflame-spells';
import { RADIANTFLAMES_SPELL_EFFECTS } from './radiantflames-spells';
import { MIASMA_SPELL_EFFECTS } from './miasma-spells';
import { SHADOWGLASS_SPELL_EFFECTS } from './shadowglass-spells';
import { SOUL_SPELL_EFFECTS, TIME_SPELL_EFFECTS, PLASMA_SPELL_EFFECTS } from './exotic-new-spells';
// Combine all spell effects into SPELL_EFFECTS
export const SPELL_EFFECTS = {
@@ -23,4 +29,12 @@ export const SPELL_EFFECTS = {
...TIER2_SPELL_EFFECTS,
...TIER3_SPELL_EFFECTS,
...LEGENDARY_SPELL_EFFECTS,
...FROST_SPELL_EFFECTS,
...BLACKFLAME_SPELL_EFFECTS,
...RADIANTFLAMES_SPELL_EFFECTS,
...MIASMA_SPELL_EFFECTS,
...SHADOWGLASS_SPELL_EFFECTS,
...SOUL_SPELL_EFFECTS,
...TIME_SPELL_EFFECTS,
...PLASMA_SPELL_EFFECTS,
};
@@ -0,0 +1,58 @@
// ─── Miasma Spell Effects ───────────────────────────────────────
// Miasma spells - Air + Death compound, toxic/plague/armor corrosion focus
import type { EnchantmentEffectDef } from './types';
import { ALL_CASTER } from './types';
export const MIASMA_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_toxicCloud: {
id: 'spell_toxicCloud',
name: 'Toxic Cloud',
description: 'Grants the ability to cast Toxic Cloud (9 miasma damage, poison)',
category: 'spell',
baseCapacityCost: 76,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'toxicCloud' }
},
spell_plagueTouch: {
id: 'spell_plagueTouch',
name: 'Plague Touch',
description: 'Grants the ability to cast Plague Touch (16 miasma damage, poison+corrode)',
category: 'spell',
baseCapacityCost: 100,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'plagueTouch' }
},
spell_miasmaBurst: {
id: 'spell_miasmaBurst',
name: 'Miasma Burst',
description: 'Grants the ability to cast Miasma Burst (32 miasma damage, AoE poison+corrode)',
category: 'spell',
baseCapacityCost: 165,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'miasmaBurst' }
},
spell_pestilence: {
id: 'spell_pestilence',
name: 'Pestilence',
description: 'Grants the ability to cast Pestilence (48 miasma damage, poison+corrode)',
category: 'spell',
baseCapacityCost: 195,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'pestilence' }
},
spell_deathMiasma: {
id: 'spell_deathMiasma',
name: 'Death Miasma',
description: 'Grants the ability to cast Death Miasma (130 miasma damage, AoE poison+corrode)',
category: 'spell',
baseCapacityCost: 390,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'deathMiasma' }
},
};
@@ -0,0 +1,58 @@
// ─── Radiant Flames Spell Effects ──────────────────────────────
// Radiant Flames spells - Light + Fire compound, blinding/heavy DoT focus
import type { EnchantmentEffectDef } from './types';
import { ALL_CASTER } from './types';
export const RADIANTFLAMES_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_radiantBurst: {
id: 'spell_radiantBurst',
name: 'Radiant Burst',
description: 'Grants the ability to cast Radiant Burst (14 radiantflames damage, burn+blind)',
category: 'spell',
baseCapacityCost: 85,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'radiantBurst' }
},
spell_holyFlame: {
id: 'spell_holyFlame',
name: 'Holy Flame',
description: 'Grants the ability to cast Holy Flame (22 radiantflames damage, burn)',
category: 'spell',
baseCapacityCost: 108,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'holyFlame' }
},
spell_blindingSun: {
id: 'spell_blindingSun',
name: 'Blinding Sun',
description: 'Grants the ability to cast Blinding Sun (40 radiantflames damage, AoE blind+burn)',
category: 'spell',
baseCapacityCost: 180,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'blindingSun' }
},
spell_purifyingFire: {
id: 'spell_purifyingFire',
name: 'Purifying Fire',
description: 'Grants the ability to cast Purifying Fire (58 radiantflames damage, heavy burn)',
category: 'spell',
baseCapacityCost: 215,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'purifyingFire' }
},
spell_supernovaBlast: {
id: 'spell_supernovaBlast',
name: 'Supernova Blast',
description: 'Grants the ability to cast Supernova Blast (150 radiantflames damage, blind+burn)',
category: 'spell',
baseCapacityCost: 420,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'supernovaBlast' }
},
};
@@ -0,0 +1,58 @@
// ─── Shadow Glass Spell Effects ──────────────────────────────────
// Shadow Glass spells - Earth + Dark compound, spike/armor pierce focus
import type { EnchantmentEffectDef } from './types';
import { ALL_CASTER } from './types';
export const SHADOWGLASS_SPELL_EFFECTS: Record<string, EnchantmentEffectDef> = {
spell_shadowSpike: {
id: 'spell_shadowSpike',
name: 'Shadow Spike',
description: 'Grants the ability to cast Shadow Spike (15 shadowglass damage, armor pierce)',
category: 'spell',
baseCapacityCost: 88,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'shadowSpike' }
},
spell_darkShard: {
id: 'spell_darkShard',
name: 'Dark Shard',
description: 'Grants the ability to cast Dark Shard (24 shadowglass damage, armor pierce)',
category: 'spell',
baseCapacityCost: 115,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'darkShard' }
},
spell_obsidianStorm: {
id: 'spell_obsidianStorm',
name: 'Obsidian Storm',
description: 'Grants the ability to cast Obsidian Storm (42 shadowglass damage, AoE armor pierce)',
category: 'spell',
baseCapacityCost: 185,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'obsidianStorm' }
},
spell_voidBlade: {
id: 'spell_voidBlade',
name: 'Void Blade',
description: 'Grants the ability to cast Void Blade (60 shadowglass damage, high armor pierce)',
category: 'spell',
baseCapacityCost: 225,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'voidBlade' }
},
spell_shadowGlassCataclysm: {
id: 'spell_shadowGlassCataclysm',
name: 'Shadow Glass Cataclysm',
description: 'Grants the ability to cast Shadow Glass Cataclysm (155 shadowglass damage, armor pierce)',
category: 'spell',
baseCapacityCost: 415,
maxStacks: 1,
allowedEquipmentCategories: ALL_CASTER,
effect: { type: 'spell', spellId: 'shadowGlassCataclysm' }
},
};
+14 -1
View File
@@ -41,7 +41,20 @@ export const MANA_TYPE_LABELS: Record<string, string> = {
earth: '⛰️ Earth',
light: '☀️ Light',
dark: '🌑 Dark',
death: '💀 Death',
transference: '🔗 Transference',
metal: '🔩 Metal',
crystal: '💎 Crystal',
sand: '🏜️ Sand',
lightning: '⚡ Lightning',
frost: '❄️ Frost',
blackflame: '🌋 BlackFlame',
radiantflames: '🌟 Radiant Flames',
miasma: '☁️ Miasma',
shadowglass: '🖤 Shadow Glass',
crystal: '💎 Crystal',
stellar: '⭐ Stellar',
void: '🕳️ Void',
soul: '💫 Soul',
time: '⏱️ Time',
plasma: '⚡ Plasma',
};
+99 -61
View File
@@ -1,14 +1,14 @@
// ─── Static Guardian Definitions ─────────────────────────────────────────────────
// New 9-tier progression for guardians:
// Expanded guardian progression:
//
// Tier 1: Base Elements (floors 1080)
// Fire, Water, Air, Earth, Light, Dark, Death, Transference
// Tier 2: Composite Elements (floors 90120)
// Metal, Sand, Lightning
// Tier 3: Composite + Components (floors 130160)
// Tier 4: Exotic Elements (floors 170200)
// Tier 2: Composite Elements (floors 90160)
// Metal, Sand, Lightning, Frost, BlackFlame, Radiant Flames, Miasma, Shadow Glass
// Tier 3: Exotic Elements (floors 170240)
// Crystal, Stellar, Void, Soul, Time, Plasma + convergence guards
//
// Floors 210+ are procedurally generated in guardian-encounters.ts.
// Floors 250+ are procedurally generated in guardian-encounters.ts.
import type { GuardianDef } from '../types';
import { resolveMultiUnlockChain } from '../utils/guardian-utils';
@@ -156,7 +156,9 @@ const TIER1: Record<number, GuardianDef> = {
};
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 2: Composite Elements (Floors 90120)
// TIER 2: Composite Elements (Floors 90160) — 8 guardians
// Original: Metal, Sand, Lightning
// New: Frost, BlackFlame, Radiant Flames, Miasma, Shadow Glass
// ═══════════════════════════════════════════════════════════════════════════════
const TIER2: Record<number, GuardianDef> = {
@@ -187,60 +189,60 @@ const TIER2: Record<number, GuardianDef> = {
[{ type: 'chain', value: 2 }],
{ shield: 800, shieldRegen: 20, barrier: 0.05, barrierRegen: 0.01 },
),
120: mk(120, '', ['frost'], '#A8D8EA', 0.28, 4.25,
[
{ type: 'elementalDamage', value: 15, desc: '+15% Frost damage' },
{ type: 'castingSpeed', value: 10, desc: '+10% casting speed' },
],
'Frost spells freeze enemies, reducing their attack speed by 20%',
[{ type: 'freeze', value: 0.2 }],
{ shield: 900, shieldRegen: 22, barrier: 0.08, barrierRegen: 0.02 },
),
130: mk(130, '', ['blackflame'], '#8B2500', 0.32, 4.5,
[
{ type: 'elementalDamage', value: 20, desc: '+20% BlackFlame damage' },
{ type: 'rawDamage', value: 10, desc: '+10% raw damage' },
],
'BlackFlame spells apply a curse that reduces enemy resistances by 15%',
[{ type: 'curse', value: 0.15 }, { type: 'burn', value: 0.15 }],
{ shield: 1000, shieldRegen: 25, healthRegen: 5, healthRegenIsPercent: true },
),
140: mk(140, '', ['radiantflames'], '#FFAA33', 0.25, 4.75,
[
{ type: 'elementalDamage', value: 15, desc: '+15% Radiant Flames damage' },
{ type: 'insightGain', value: 10, desc: '+10% insight gain' },
],
'Radiant Flames spells blind enemies, reducing their accuracy and damage by 15%',
[{ type: 'blind', value: 0.15 }, { type: 'burn', value: 0.1 }],
{ barrier: 0.12, barrierRegen: 0.03, healthRegen: 6, healthRegenIsPercent: true },
),
150: mk(150, '', ['miasma'], '#6B8E23', 0.28, 5.0,
[
{ type: 'elementalDamage', value: 15, desc: '+15% Miasma damage' },
{ type: 'maxMana', value: 200, desc: '+200 max mana' },
],
'Miasma spells corrode armor and spread plague in swarm rooms',
[{ type: 'corrosion', value: 0.2 }, { type: 'poison', value: 0.15 }],
{ shield: 1100, shieldRegen: 28, barrier: 0.05, barrierRegen: 0.01 },
),
160: mk(160, '', ['shadowglass'], '#2C2C54', 0.33, 5.25,
[
{ type: 'elementalDamage', value: 20, desc: '+20% Shadow Glass damage' },
{ type: 'critDamage', value: 15, desc: '+15% crit damage' },
],
'Shadow Glass spells create piercing spikes ignoring 30% armor',
[{ type: 'armor_pierce', value: 0.3 }, { type: 'pierce', value: 0.25 }],
{ shield: 1200, shieldRegen: 30, healthRegen: 5, healthRegenIsPercent: true },
),
};
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 3: Composite + Their Components (Floors 130160)
// TIER 3: Exotic Elements (Floors 170240) — 6 exotics + 2 convergence guards
// Original: Crystal, Stellar, Void (floors 170-200)
// New: Soul, Time, Plasma + a convergence guardian
// ═══════════════════════════════════════════════════════════════════════════════
const TIER3: Record<number, GuardianDef> = {
130: mk(130, '', ['metal', 'fire', 'earth'], '#D4A574', 0.35, 4.5,
[
{ type: 'elementalDamage', value: 20, desc: '+20% Metal damage' },
{ type: 'elementalDamage', value: 10, desc: '+10% Fire damage' },
{ type: 'elementalDamage', value: 10, desc: '+10% Earth damage' },
],
'Tri-aspect: Metal, Fire, and Earth spells gain +10% effectiveness',
[{ type: 'armor_pierce', value: 0.25 }, { type: 'burn', value: 0.1 }],
{ shield: 1000, shieldRegen: 25, barrier: 0.05, barrierRegen: 0.01 },
),
140: mk(140, '', ['sand', 'earth', 'water'], '#C9B896', 0.30, 4.75,
[
{ type: 'elementalDamage', value: 20, desc: '+20% Sand damage' },
{ type: 'elementalDamage', value: 10, desc: '+10% Earth damage' },
{ type: 'elementalDamage', value: 10, desc: '+10% Water damage' },
],
'Tri-aspect: Sand, Earth, and Water spells gain +10% effectiveness',
[{ type: 'slow', value: 0.3 }, { type: 'armor_pierce', value: 0.15 }],
{ barrier: 0.12, barrierRegen: 0.03, healthRegen: 6, healthRegenIsPercent: true },
),
150: mk(150, '', ['lightning', 'fire', 'air'], '#FFE066', 0.28, 5.0,
[
{ type: 'elementalDamage', value: 20, desc: '+20% Lightning damage' },
{ type: 'elementalDamage', value: 10, desc: '+10% Fire damage' },
{ type: 'elementalDamage', value: 10, desc: '+10% Air damage' },
],
'Tri-aspect: Lightning, Fire, and Air spells gain +10% effectiveness',
[{ type: 'chain', value: 2 }, { type: 'cast_speed', value: 0.1 }],
{ shield: 1200, shieldRegen: 30, healthRegen: 5, healthRegenIsPercent: true },
),
160: mk(160, '', ['metal', 'lightning', 'fire', 'earth', 'air'], '#E8C872', 0.35, 5.25,
[
{ type: 'elementalDamage', value: 15, desc: '+15% Metal damage' },
{ type: 'elementalDamage', value: 15, desc: '+15% Lightning damage' },
{ type: 'rawDamage', value: 10, desc: '+10% raw damage' },
],
'Fused aspects: Lightning spells gain +20% armor pierce; Metal spells chain once',
[{ type: 'armor_pierce', value: 0.3 }, { type: 'chain', value: 1 }],
{ shield: 1500, shieldRegen: 40, barrier: 0.08, barrierRegen: 0.02, healthRegen: 7, healthRegenIsPercent: true },
),
};
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 4: Exotic Elements (Floors 170200)
// ═══════════════════════════════════════════════════════════════════════════════
const TIER4: Record<number, GuardianDef> = {
170: mk(170, '', ['crystal'], '#85C1E9', 0.35, 5.5,
[
{ type: 'elementalDamage', value: 20, desc: '+20% Crystal damage' },
@@ -270,15 +272,52 @@ const TIER4: Record<number, GuardianDef> = {
[{ type: 'resist_ignore', value: 0.4 }],
{ shield: 2500, shieldRegen: 60, barrier: 0.10, barrierRegen: 0.02, healthRegen: 6, healthRegenIsPercent: true },
),
200: mk(200, '', ['crystal', 'stellar', 'void'], '#B39DDB', 0.40, 7.0,
200: mk(200, '', ['soul'], '#E8D5F5', 0.30, 7.0,
[
{ type: 'elementalDamage', value: 25, desc: '+25% Soul damage' },
{ type: 'rawDamage', value: 20, desc: '+20% raw damage' },
],
'Soul spells bypass all defenses and shields',
[{ type: 'defense_pierce', value: 0.5 }, { type: 'mana_drain', value: 0.2 }],
{ shield: 2800, shieldRegen: 55, barrier: 0.08, barrierRegen: 0.02 },
),
210: mk(210, '', ['time'], '#C5B99A', 0.32, 7.5,
[
{ type: 'elementalDamage', value: 20, desc: '+20% Time damage' },
{ type: 'castingSpeed', value: 20, desc: '+20% casting speed' },
],
'Time spells slow enemies by 30% and reduce dodge by 20%',
[{ type: 'slow', value: 0.3 }, { type: 'temporal_snap', value: 0.15 }],
{ barrier: 0.15, barrierRegen: 0.04, healthRegen: 9, healthRegenIsPercent: true },
),
220: mk(220, '', ['plasma'], '#FF6B9D', 0.28, 8.0,
[
{ type: 'elementalDamage', value: 25, desc: '+25% Plasma damage' },
{ type: 'manaRegen', value: 2.5, desc: '+2.5 mana regen' },
],
'Plasma spells chain to 3 targets with 30% damage each',
[{ type: 'chain', value: 3 }, { type: 'burn', value: 0.1 }],
{ shield: 3200, shieldRegen: 70, barrier: 0.10, barrierRegen: 0.02 },
),
230: mk(230, '', ['crystal', 'stellar', 'void'], '#B39DDB', 0.40, 8.5,
[
{ type: 'elementalDamage', value: 15, desc: '+15% Crystal damage' },
{ type: 'elementalDamage', value: 15, desc: '+15% Stellar damage' },
{ type: 'elementalDamage', value: 15, desc: '+15% Void damage' },
],
'Exotic convergence: All exotic spells gain +15% effectiveness',
[{ type: 'reflect', value: 0.1 }, { type: 'resist_ignore', value: 0.1 }],
{ shield: 3000, shieldRegen: 80, barrier: 0.12, barrierRegen: 0.03, healthRegen: 10, healthRegenIsPercent: true },
'Primordial gaze: Crystal/Stellar/Void spells gain +20% effectiveness',
[{ type: 'reflect', value: 0.1 }, { type: 'resist_ignore', value: 0.15 }],
{ shield: 3500, shieldRegen: 90, barrier: 0.12, barrierRegen: 0.03 },
),
240: mk(240, '', ['soul', 'time', 'plasma'], '#D5A0E0', 0.42, 9.0,
[
{ type: 'elementalDamage', value: 15, desc: '+15% Soul damage' },
{ type: 'elementalDamage', value: 15, desc: '+15% Time damage' },
{ type: 'elementalDamage', value: 15, desc: '+15% Plasma damage' },
],
'Astral convergence: Soul/Time/Plasma spells gain +20% effectiveness',
[{ type: 'defense_pierce', value: 0.2 }, { type: 'chain', value: 1 }],
{ shield: 3800, shieldRegen: 100, barrier: 0.14, barrierRegen: 0.03, healthRegen: 12, healthRegenIsPercent: true },
),
};
@@ -290,7 +329,6 @@ const STATIC_GUARDIANS: Record<number, GuardianDef> = {
...TIER1,
...TIER2,
...TIER3,
...TIER4,
};
export { STATIC_GUARDIANS, TIER1, TIER2, TIER3, TIER4 };
export { STATIC_GUARDIANS, TIER1, TIER2, TIER3 };
+80 -67
View File
@@ -3,14 +3,13 @@
//
// Guardian progression (9 tiers):
// Tier 1: Base Elements (static, floors 1080, guardian-data.ts)
// Tier 2: Composite Elements (static, floors 90120, guardian-data.ts)
// Tier 3: Composite+Components (static, floors 130160, guardian-data.ts)
// Tier 4: Exotic Elements (static, floors 170200, guardian-data.ts)
// Tier 5: Dual Element Pairs (dynamic, floors 210240, this file)
// Tier 6: Dual Comp+Components (dynamic, floors 250290, this file)
// Tier 7: Exotic+Components (dynamic, floors 300340, this file)
// Tier 8: Exotic+Comp+Components (dynamic, floors 350390, this file)
// Tier 9: Full Fusion (dynamic, floors 400+, this file)
// Tier 2: Composite Elements (static, floors 90160, guardian-data.ts)
// Tier 3: Exotic Elements (static, floors 170240, guardian-data.ts)
// Tier 4: Dual Element Pairs (dynamic, floors 250280, this file)
// Tier 5: Dual Comp+Components (dynamic, floors 290330, this file)
// Tier 6: Exotic+Components (dynamic, floors 340380, this file)
// Tier 7: Exotic+Comp+Components (dynamic, floors 390430, this file)
// Tier 8: Full Fusion (dynamic, floors 440+, this file)
//
// All lookups go through getGuardianForFloor() which merges static + procedural.
@@ -35,6 +34,14 @@ const GUARDIAN_PREFIXES: Record<string, string[]> = {
crystal: ['Prism', 'Gemma', 'Crystal', 'Shard', 'Facet'],
stellar: ['Astro', 'Stella', 'Nova', 'Cosmo', 'Lumin'],
void: ['Void', 'Abyss', 'Null', 'Nihil', 'Obliv'],
frost: ['Glac', 'Cryo', 'Bore', 'Rime', 'Frost'],
blackflame: ['Umbra', 'Cinder', 'Ash', 'Smoke', 'Ember'],
radiantflames: ['Sol', 'Radi', 'Aura', 'Glow', 'Flare'],
miasma: ['Mias', 'Tox', 'Plague', 'Virus', 'Blight'],
shadowglass: ['Shade', 'Obsid', 'Night', 'Gloom', 'Void'],
soul: ['Psy', 'Anima', 'Spirit', 'Ghost', 'Wraith'],
time: ['Chron', 'Temp', 'Epoch', 'Aeon', 'Hour'],
plasma: ['Ion', 'Plasm', 'Spark', 'Arc', 'Flux'],
};
const GUARDIAN_TITLES: string[] = [
@@ -67,8 +74,8 @@ export function getGuardianHP(floor: number): number {
// ─── Tier Helpers ───────────────────────────────────────────────────────────────
const BASE_ELEMENTS = ['fire', 'water', 'air', 'earth', 'light', 'dark', 'death'];
const COMPOSITE_ELEMENTS = ['metal', 'sand', 'lightning'];
const EXOTIC_ELEMENTS = ['crystal', 'stellar', 'void'];
const COMPOSITE_ELEMENTS = ['metal', 'sand', 'lightning', 'frost', 'blackflame', 'radiantflames', 'miasma', 'shadowglass'];
const EXOTIC_ELEMENTS = ['crystal', 'stellar', 'void', 'soul', 'time', 'plasma'];
/** Generate boon elements (max 3) */
function makeBoons(elements: string[], floor: number): GuardianBoon[] {
@@ -80,16 +87,16 @@ function makeBoons(elements: string[], floor: number): GuardianBoon[] {
}
function getTier(floor: number): number {
if (floor >= 400) return 9;
if (floor >= 350) return 8;
if (floor >= 300) return 7;
if (floor >= 250) return 6;
if (floor >= 210) return 5;
if (floor >= 440) return 8;
if (floor >= 390) return 7;
if (floor >= 340) return 6;
if (floor >= 290) return 5;
if (floor >= 250) return 4;
return 0; // Static tiers
}
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 5: Dual Element Pairs (Floors 210240)
// TIER 4: Dual Element Pairs (Floors 250280)
// ═══════════════════════════════════════════════════════════════════════════════
const DUAL_PAIRS: [string, string][] = [
@@ -104,23 +111,23 @@ const DUAL_PAIRS: [string, string][] = [
['earth', 'death'],
];
function getTier5Guardian(floor: number): GuardianDef {
const idx = Math.floor((floor - 210) / 10) % DUAL_PAIRS.length;
function getTier4Guardian(floor: number): GuardianDef {
const idx = Math.floor((floor - 250) / 10) % DUAL_PAIRS.length;
const [el1, el2] = DUAL_PAIRS[idx];
const elements = [el1, el2];
const hpVal = getGuardianHP(floor);
const armor = Math.min(0.5, 0.30 + (floor - 210) * 0.003);
const armor = Math.min(0.5, 0.30 + (floor - 250) * 0.003);
return {
name: '',
element: elements,
hp: hpVal,
pact: 7.5 + (floor - 210) * 0.05,
pact: 7.5 + (floor - 250) * 0.05,
color: blendColors(el1, el2),
armor,
boons: makeBoons(elements, floor),
pactCost: Math.floor(hpVal * 0.3 + hpVal * armor * 0.5),
pactTime: 20 + Math.floor((floor - 210) / 10),
pactTime: 20 + Math.floor((floor - 250) / 10),
uniquePerk: `Dual-aspect: ${el1} and ${el2} spells gain +20% effectiveness`,
power: Math.floor(hpVal * 0.5),
effects: [
@@ -129,16 +136,16 @@ function getTier5Guardian(floor: number): GuardianDef {
],
signingCost: {
mana: Math.floor(hpVal * 0.3),
time: 20 + Math.floor((floor - 210) / 10),
time: 20 + Math.floor((floor - 250) / 10),
},
unlocksMana: resolveMultiUnlockChain(elements),
damageMultiplier: 3.5 + (floor - 210) * 0.02,
insightMultiplier: 3.0 + (floor - 210) * 0.01,
damageMultiplier: 3.5 + (floor - 250) * 0.02,
insightMultiplier: 3.0 + (floor - 250) * 0.01,
};
}
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 6: Dual Composite + Components (Floors 250290)
// TIER 5: Dual Composite + Components (Floors 290330)
// Pairs of composites with all their base components.
// ═══════════════════════════════════════════════════════════════════════════════
@@ -146,25 +153,28 @@ const DUAL_COMP_PAIRS: [string, string][] = [
['metal', 'sand'],
['metal', 'lightning'],
['sand', 'lightning'],
['frost', 'blackflame'],
['radiantflames', 'miasma'],
['shadowglass', 'frost'],
];
function getTier6Guardian(floor: number): GuardianDef {
const idx = Math.floor((floor - 250) / 10) % DUAL_COMP_PAIRS.length;
function getTier5Guardian(floor: number): GuardianDef {
const idx = Math.floor((floor - 290) / 10) % DUAL_COMP_PAIRS.length;
const [comp1, comp2] = DUAL_COMP_PAIRS[idx];
const elements = resolveMultiUnlockChain([comp1, comp2]);
const hpVal = getGuardianHP(floor);
const armor = Math.min(0.55, 0.35 + (floor - 250) * 0.003);
const armor = Math.min(0.55, 0.35 + (floor - 290) * 0.003);
return {
name: '',
element: elements,
hp: hpVal,
pact: 9.0 + (floor - 250) * 0.05,
pact: 9.0 + (floor - 290) * 0.05,
color: blendColors(comp1, comp2),
armor,
boons: makeBoons([comp1, comp2], floor),
pactCost: Math.floor(hpVal * 0.3 + hpVal * armor * 0.5),
pactTime: 24 + Math.floor((floor - 250) / 10),
pactTime: 24 + Math.floor((floor - 290) / 10),
uniquePerk: `Fusion twin-aspect: ${comp1} and ${comp2} spells gain +25% effectiveness`,
power: Math.floor(hpVal * 0.55),
effects: [
@@ -173,36 +183,36 @@ function getTier6Guardian(floor: number): GuardianDef {
],
signingCost: {
mana: Math.floor(hpVal * 0.35),
time: 24 + Math.floor((floor - 250) / 10),
time: 24 + Math.floor((floor - 290) / 10),
},
unlocksMana: resolveMultiUnlockChain(elements),
damageMultiplier: 4.0 + (floor - 250) * 0.02,
insightMultiplier: 3.5 + (floor - 250) * 0.01,
damageMultiplier: 4.0 + (floor - 290) * 0.02,
insightMultiplier: 3.5 + (floor - 290) * 0.01,
};
}
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 7: Exotic + Components (Floors 300340)
// TIER 6: Exotic + Components (Floors 340380)
// Each exotic element paired with all its component base elements.
// ═══════════════════════════════════════════════════════════════════════════════
function getTier7Guardian(floor: number): GuardianDef {
const exoticIdx = Math.floor((floor - 300) / 10) % EXOTIC_ELEMENTS.length;
function getTier6Guardian(floor: number): GuardianDef {
const exoticIdx = Math.floor((floor - 340) / 10) % EXOTIC_ELEMENTS.length;
const exoticEl = EXOTIC_ELEMENTS[exoticIdx];
const chain = resolveMultiUnlockChain([exoticEl]);
const hpVal = getGuardianHP(floor);
const armor = Math.min(0.6, 0.40 + (floor - 300) * 0.003);
const armor = Math.min(0.6, 0.40 + (floor - 340) * 0.003);
return {
name: '',
element: chain,
hp: hpVal,
pact: 10.5 + (floor - 300) * 0.05,
pact: 10.5 + (floor - 340) * 0.05,
color: '#B8A9C9',
armor,
boons: [makeBoons([exoticEl], floor)[0]],
pactCost: Math.floor(hpVal * 0.35 + hpVal * armor * 0.5),
pactTime: 28 + Math.floor((floor - 300) / 10),
pactTime: 28 + Math.floor((floor - 340) / 10),
uniquePerk: `Exotic resonance: ${exoticEl} spells gain +30% effectiveness`,
power: Math.floor(hpVal * 0.6),
effects: [
@@ -211,38 +221,38 @@ function getTier7Guardian(floor: number): GuardianDef {
],
signingCost: {
mana: Math.floor(hpVal * 0.35),
time: 28 + Math.floor((floor - 300) / 10),
time: 28 + Math.floor((floor - 340) / 10),
},
unlocksMana: chain,
damageMultiplier: 4.5 + (floor - 300) * 0.02,
insightMultiplier: 4.0 + (floor - 300) * 0.01,
damageMultiplier: 4.5 + (floor - 340) * 0.02,
insightMultiplier: 4.0 + (floor - 340) * 0.01,
};
}
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 8: Exotic + Composite + Components (Floors 350390)
// TIER 7: Exotic + Composite + Components (Floors 390430)
// One exotic + one composite + all base elements.
// ═══════════════════════════════════════════════════════════════════════════════
function getTier8Guardian(floor: number): GuardianDef {
const exoticIdx = Math.floor((floor - 350) / 10) % EXOTIC_ELEMENTS.length;
const compIdx = Math.floor((floor - 350) / 10) % COMPOSITE_ELEMENTS.length;
function getTier7Guardian(floor: number): GuardianDef {
const exoticIdx = Math.floor((floor - 390) / 10) % EXOTIC_ELEMENTS.length;
const compIdx = Math.floor((floor - 390) / 10) % COMPOSITE_ELEMENTS.length;
const exoticEl = EXOTIC_ELEMENTS[exoticIdx];
const compEl = COMPOSITE_ELEMENTS[compIdx];
const elements = resolveMultiUnlockChain([exoticEl, compEl]);
const hpVal = getGuardianHP(floor);
const armor = Math.min(0.65, 0.45 + (floor - 350) * 0.003);
const armor = Math.min(0.65, 0.45 + (floor - 390) * 0.003);
return {
name: '',
element: elements,
hp: hpVal,
pact: 12.0 + (floor - 350) * 0.05,
pact: 12.0 + (floor - 390) * 0.05,
color: '#9B72AA',
armor,
boons: makeBoons([exoticEl, compEl], floor),
pactCost: Math.floor(hpVal * 0.4 + hpVal * armor * 0.5),
pactTime: 32 + Math.floor((floor - 350) / 10),
pactTime: 32 + Math.floor((floor - 390) / 10),
uniquePerk: `Primordial fusion: ${exoticEl} and ${compEl} spells gain +25% effectiveness`,
power: Math.floor(hpVal * 0.65),
effects: [
@@ -252,38 +262,38 @@ function getTier8Guardian(floor: number): GuardianDef {
],
signingCost: {
mana: Math.floor(hpVal * 0.4),
time: 32 + Math.floor((floor - 350) / 10),
time: 32 + Math.floor((floor - 390) / 10),
},
unlocksMana: elements,
damageMultiplier: 5.0 + (floor - 350) * 0.02,
insightMultiplier: 4.5 + (floor - 350) * 0.01,
damageMultiplier: 5.0 + (floor - 390) * 0.02,
insightMultiplier: 4.5 + (floor - 390) * 0.01,
};
}
// ═══════════════════════════════════════════════════════════════════════════════
// TIER 9: Full Fusion — 1 Exotic + 2 Composite + All Components (Floors 400+)
// TIER 8: Full Fusion — 1 Exotic + 2 Composite + All Components (Floors 440+)
// ═══════════════════════════════════════════════════════════════════════════════
function getTier9Guardian(floor: number): GuardianDef {
const exoticIdx = (Math.floor((floor - 400) / 10)) % EXOTIC_ELEMENTS.length;
function getTier8Guardian(floor: number): GuardianDef {
const exoticIdx = (Math.floor((floor - 440) / 10)) % EXOTIC_ELEMENTS.length;
const exoticEl = EXOTIC_ELEMENTS[exoticIdx];
// Pick 2 different composites
const comp1 = COMPOSITE_ELEMENTS[Math.floor((floor - 400) / 10) % COMPOSITE_ELEMENTS.length];
const comp2 = COMPOSITE_ELEMENTS[(Math.floor((floor - 400) / 10) + 1) % COMPOSITE_ELEMENTS.length];
const comp1 = COMPOSITE_ELEMENTS[Math.floor((floor - 440) / 10) % COMPOSITE_ELEMENTS.length];
const comp2 = COMPOSITE_ELEMENTS[(Math.floor((floor - 440) / 10) + 1) % COMPOSITE_ELEMENTS.length];
const elements = resolveMultiUnlockChain([exoticEl, comp1, comp2]);
const hpVal = getGuardianHP(floor);
const armor = Math.min(0.7, 0.50 + (floor - 400) * 0.002);
const armor = Math.min(0.7, 0.50 + (floor - 440) * 0.002);
return {
name: '',
element: elements,
hp: hpVal,
pact: 14.0 + (floor - 400) * 0.05,
pact: 14.0 + (floor - 440) * 0.05,
color: '#7B5E9A',
armor,
boons: makeBoons([exoticEl, comp1, comp2], floor),
pactCost: Math.floor(hpVal * 0.45 + hpVal * armor * 0.5),
pactTime: 36 + Math.floor((floor - 400) / 10),
pactTime: 36 + Math.floor((floor - 440) / 10),
uniquePerk: `Cosmic convergence: All exotic, composite, and base spells gain +15% effectiveness`,
power: Math.floor(hpVal * 0.7),
effects: [
@@ -294,11 +304,11 @@ function getTier9Guardian(floor: number): GuardianDef {
],
signingCost: {
mana: Math.floor(hpVal * 0.45),
time: 36 + Math.floor((floor - 400) / 10),
time: 36 + Math.floor((floor - 440) / 10),
},
unlocksMana: elements,
damageMultiplier: 5.5 + (floor - 400) * 0.02,
insightMultiplier: 5.0 + (floor - 400) * 0.01,
damageMultiplier: 5.5 + (floor - 440) * 0.02,
insightMultiplier: 5.0 + (floor - 440) * 0.01,
};
}
@@ -309,6 +319,9 @@ const ELEMENT_COLORS: Record<string, string> = {
light: '#FFD700', dark: '#9B59B6', death: '#778CA3', transference: '#1ABC9C',
metal: '#BDC3C7', sand: '#D4AC0D', lightning: '#FFEB3B',
crystal: '#85C1E9', stellar: '#F0E68C', void: '#4A235A',
frost: '#A8D8EA', blackflame: '#8B2500', radiantflames: '#FFAA33',
miasma: '#6B8E23', shadowglass: '#2C2C54',
soul: '#E8D5F5', time: '#C5B99A', plasma: '#FF6B9D',
};
function blendColors(el1: string, el2: string): string {
@@ -327,17 +340,17 @@ function blendColors(el1: string, el2: string): string {
// ─── Procedural Guardian Generator ─────────────────────────────────────────────
function getProceduralGuardian(floor: number): GuardianDef | null {
if (floor < 210 || floor % 10 !== 0) return null;
if (floor < 250 || floor % 10 !== 0) return null;
const tier = getTier(floor);
let g: GuardianDef;
switch (tier) {
case 4: g = getTier4Guardian(floor); break;
case 5: g = getTier5Guardian(floor); break;
case 6: g = getTier6Guardian(floor); break;
case 7: g = getTier7Guardian(floor); break;
case 8: g = getTier8Guardian(floor); break;
case 9: g = getTier9Guardian(floor); break;
default: return null;
}
@@ -363,9 +376,9 @@ export function getGuardianForFloor(floor: number): GuardianDef | null {
export function getAllGuardianFloors(): number[] {
// Static floors from guardian-data.ts
const staticFloors = Object.keys(STATIC_GUARDIANS).map(Number);
// Procedural floors: every 10th floor from 210 to 450
// Procedural floors: every 10th floor from 250 to 490
const proceduralFloors: number[] = [];
for (let f = 210; f <= 450; f += 10) {
for (let f = 250; f <= 490; f += 10) {
proceduralFloors.push(f);
}
const all = new Set([...staticFloors, ...proceduralFloors]);