2f580ef0fe
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m30s
- Fix multi-element guardians (floors 130,140,150,170,190,200,210,230,240) to have exactly 2 boons per spec instead of 3-4 - Fix signedPactDetails never being populated: pipeline processPactRitual now includes signedPactDetails in writes with floor, guardianId, signedAt time, and skillLevels - Fix completePactRitual in prestigeStore to also populate signedPactDetails - Update gameStore.ts call site to pass signedPactDetails and current day/hour to processPactRitual Fixes #309, fixes #308
331 lines
15 KiB
TypeScript
331 lines
15 KiB
TypeScript
// ─── Static Guardian Definitions ─────────────────────────────────────────────────
|
||
// Expanded guardian progression:
|
||
//
|
||
// Tier 1: Base Elements (floors 10–80)
|
||
// Fire, Water, Air, Earth, Light, Dark, Death, Transference
|
||
// Tier 2: Composite Elements (floors 90–160)
|
||
// Metal, Sand, Lightning, Frost, BlackFlame, Radiant Flames, Miasma, Shadow Glass
|
||
// Tier 3: Exotic Elements (floors 170–240)
|
||
// Crystal, Stellar, Void, Soul, Time, Plasma + convergence guards
|
||
//
|
||
// Floors 250+ are procedurally generated in guardian-encounters.ts.
|
||
|
||
import type { GuardianDef } from '../types';
|
||
import { resolveMultiUnlockChain } from '../utils/guardian-utils';
|
||
|
||
// ─── Shared Helpers ─────────────────────────────────────────────────────────────
|
||
|
||
function hp(floor: number): number {
|
||
const base = 5000;
|
||
const exponent = 1.1 + (floor / 200);
|
||
return Math.floor(base * Math.pow(floor / 10, exponent));
|
||
}
|
||
|
||
function pactCost(hpVal: number, power: number, armor: number, shield: number, barrier: number): number {
|
||
return Math.floor(hpVal * 0.3 + power * 5 + hpVal * armor * 0.5 + shield * 2 + hpVal * barrier * 0.3);
|
||
}
|
||
|
||
function mk(
|
||
floor: number,
|
||
name: string,
|
||
element: string[],
|
||
color: string,
|
||
armor: number,
|
||
pactMult: number,
|
||
boons: GuardianDef['boons'],
|
||
uniquePerk: string,
|
||
effects: GuardianDef['effects'],
|
||
defensive?: {
|
||
shield?: number;
|
||
shieldRegen?: number;
|
||
barrier?: number;
|
||
barrierRegen?: number;
|
||
healthRegen?: number;
|
||
healthRegenIsPercent?: boolean;
|
||
},
|
||
): GuardianDef {
|
||
const hpVal = hp(floor);
|
||
const power = Math.floor(hpVal * 0.5);
|
||
const arm = armor;
|
||
const shield = defensive?.shield ?? 0;
|
||
const barrier = defensive?.barrier ?? 0;
|
||
const pc = pactCost(hpVal, power, arm, shield, barrier);
|
||
const pt = 2 + Math.floor(floor / 10);
|
||
|
||
return {
|
||
name,
|
||
element,
|
||
hp: hpVal,
|
||
pact: pactMult,
|
||
color,
|
||
armor: arm,
|
||
shield,
|
||
shieldRegen: defensive?.shieldRegen ?? 0,
|
||
barrier,
|
||
barrierRegen: defensive?.barrierRegen ?? 0,
|
||
healthRegen: defensive?.healthRegen ?? 0,
|
||
healthRegenIsPercent: defensive?.healthRegenIsPercent ?? false,
|
||
boons,
|
||
pactCost: pc,
|
||
pactTime: pt,
|
||
uniquePerk,
|
||
power,
|
||
effects,
|
||
signingCost: { mana: pc, time: pt },
|
||
unlocksMana: resolveMultiUnlockChain(element),
|
||
damageMultiplier: 1.0 + floor * 0.01,
|
||
insightMultiplier: 1.0 + floor * 0.005,
|
||
};
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════════════════════
|
||
// TIER 1: Base Elements (Floors 10–80)
|
||
// ═══════════════════════════════════════════════════════════════════════════════
|
||
|
||
const TIER1: Record<number, GuardianDef> = {
|
||
10: mk(10, 'Ignis Prime', ['fire'], '#FF6B35', 0.10, 1.5,
|
||
[
|
||
{ type: 'elementalDamage', value: 5, desc: '+5% Fire damage' },
|
||
{ type: 'maxMana', value: 50, desc: '+50 max mana' },
|
||
],
|
||
'Fire spells cast 10% faster',
|
||
[{ type: 'burn', value: 0.1 }],
|
||
),
|
||
20: mk(20, 'Aqua Regia', ['water'], '#4ECDC4', 0.15, 1.75,
|
||
[
|
||
{ type: 'elementalDamage', value: 5, desc: '+5% Water damage' },
|
||
{ type: 'manaRegen', value: 0.5, desc: '+0.5 mana regen' },
|
||
],
|
||
'Water spells deal +15% damage',
|
||
[{ type: 'armor_pierce', value: 0.15 }],
|
||
{ healthRegen: 10, healthRegenIsPercent: false },
|
||
),
|
||
30: mk(30, 'Ventus Rex', ['air'], '#00D4FF', 0.18, 2.0,
|
||
[
|
||
{ type: 'elementalDamage', value: 5, desc: '+5% Air damage' },
|
||
{ type: 'castingSpeed', value: 5, desc: '+5% casting speed' },
|
||
],
|
||
'Air spells have 15% crit chance',
|
||
[{ type: 'cast_speed', value: 0.05 }],
|
||
),
|
||
40: mk(40, 'Terra Firma', ['earth'], '#F4A261', 0.25, 2.25,
|
||
[
|
||
{ type: 'elementalDamage', value: 5, desc: '+5% Earth damage' },
|
||
{ type: 'maxMana', value: 100, desc: '+100 max mana' },
|
||
],
|
||
'Earth spells deal +25% damage to guardians',
|
||
[{ type: 'armor_pierce', value: 0.2 }],
|
||
{ shield: 200, shieldRegen: 5 },
|
||
),
|
||
50: mk(50, 'Lux Aeterna', ['light'], '#FFD700', 0.20, 2.5,
|
||
[
|
||
{ type: 'elementalDamage', value: 10, desc: '+10% Light damage' },
|
||
{ type: 'insightGain', value: 10, desc: '+10% insight gain' },
|
||
],
|
||
'Light spells reveal enemy weaknesses (+20% damage)',
|
||
[{ type: 'crit_chance', value: 0.1 }],
|
||
{ barrier: 0.05, barrierRegen: 0.01 },
|
||
),
|
||
60: mk(60, 'Umbra Mortis', ['dark'], '#9B59B6', 0.22, 2.75,
|
||
[
|
||
{ type: 'elementalDamage', value: 10, desc: '+10% Dark damage' },
|
||
{ type: 'critDamage', value: 15, desc: '+15% crit damage' },
|
||
],
|
||
'Dark spells deal +25% damage to armored enemies',
|
||
[{ type: 'crit_damage', value: 0.15 }],
|
||
{ healthRegen: 5, healthRegenIsPercent: true },
|
||
),
|
||
70: mk(70, 'Mors Ultima', ['death'], '#778CA3', 0.25, 3.0,
|
||
[
|
||
{ type: 'elementalDamage', value: 10, desc: '+10% Death damage' },
|
||
{ type: 'rawDamage', value: 10, desc: '+10% raw damage' },
|
||
],
|
||
'Death spells execute enemies below 20% HP',
|
||
[{ type: 'raw_damage', value: 0.1 }],
|
||
{ shield: 400, shieldRegen: 10 },
|
||
),
|
||
80: mk(80, 'Vinculum Arcana', ['transference'], '#1ABC9C', 0.20, 3.25,
|
||
[
|
||
{ type: 'maxMana', value: 150, desc: '+150 max mana' },
|
||
{ type: 'manaRegen', value: 1.0, desc: '+1.0 mana regen' },
|
||
],
|
||
'Transference spells have 25% reduced cost',
|
||
[{ type: 'cost_reduction', value: 0.25 }],
|
||
{ barrier: 0.08, barrierRegen: 0.02, healthRegen: 3, healthRegenIsPercent: true },
|
||
),
|
||
};
|
||
|
||
// ═══════════════════════════════════════════════════════════════════════════════
|
||
// TIER 2: Composite Elements (Floors 90–160) — 8 guardians
|
||
// Original: Metal, Sand, Lightning
|
||
// New: Frost, BlackFlame, Radiant Flames, Miasma, Shadow Glass
|
||
// ═══════════════════════════════════════════════════════════════════════════════
|
||
|
||
const TIER2: Record<number, GuardianDef> = {
|
||
90: mk(90, '', ['metal'], '#BDC3C7', 0.30, 3.5,
|
||
[
|
||
{ type: 'elementalDamage', value: 15, desc: '+15% Metal damage' },
|
||
{ type: 'maxMana', value: 150, desc: '+150 max mana' },
|
||
],
|
||
'Metal spells pierce 20% armor',
|
||
[{ type: 'armor_pierce', value: 0.2 }],
|
||
{ shield: 600, shieldRegen: 15, healthRegen: 4, healthRegenIsPercent: true },
|
||
),
|
||
100: mk(100, '', ['sand'], '#D4AC0D', 0.25, 3.75,
|
||
[
|
||
{ type: 'elementalDamage', value: 15, desc: '+15% Sand damage' },
|
||
{ type: 'manaRegen', value: 1.5, desc: '+1.5 mana regen' },
|
||
],
|
||
'Sand spells slow enemies by 25%',
|
||
[{ type: 'slow', value: 0.25 }],
|
||
{ barrier: 0.10, barrierRegen: 0.03, healthRegen: 5, healthRegenIsPercent: true },
|
||
),
|
||
110: mk(110, '', ['lightning'], '#FFEB3B', 0.22, 4.0,
|
||
[
|
||
{ type: 'elementalDamage', value: 15, desc: '+15% Lightning damage' },
|
||
{ type: 'castingSpeed', value: 15, desc: '+15% casting speed' },
|
||
],
|
||
'Lightning spells chain to 2 additional targets',
|
||
[{ 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, '', ['metal', 'fire', 'earth'], '#8B2500', 0.32, 4.5,
|
||
[
|
||
{ type: 'elementalDamage', value: 15, desc: '+15% BlackFlame damage' },
|
||
{ type: 'rawDamage', value: 10, desc: '+10% raw damage' },
|
||
],
|
||
'Multi-element BlackFlame spells apply a curse that reduces enemy resistances by 15%',
|
||
[{ type: 'curse', value: 0.15 }, { type: 'burn', value: 0.15 }, { type: 'armor_pierce', value: 0.2 }],
|
||
{ shield: 1000, shieldRegen: 25, healthRegen: 5, healthRegenIsPercent: true },
|
||
),
|
||
140: mk(140, '', ['sand', 'earth', 'water'], '#FFAA33', 0.25, 4.75,
|
||
[
|
||
{ type: 'elementalDamage', value: 15, desc: '+15% Radiant Earth damage' },
|
||
{ type: 'maxMana', value: 200, desc: '+200 max mana' },
|
||
],
|
||
'Radiant Earth spells blind enemies, reducing their accuracy and damage by 15%',
|
||
[{ type: 'blind', value: 0.15 }, { type: 'armor_pierce', value: 0.1 }],
|
||
{ barrier: 0.12, barrierRegen: 0.03, healthRegen: 6, healthRegenIsPercent: true },
|
||
),
|
||
150: mk(150, '', ['lightning', 'fire', 'air'], '#6B8E23', 0.28, 5.0,
|
||
[
|
||
{ type: 'elementalDamage', value: 15, desc: '+15% Storm Lightning damage' },
|
||
{ type: 'castingSpeed', value: 15, desc: '+15% casting speed' },
|
||
],
|
||
'Storm Lightning spells corrode armor and spread chain lightning in swarm rooms',
|
||
[{ type: 'chain', value: 2 }, { type: 'cast_speed', value: 0.1 }, { type: 'burn', value: 0.1 }],
|
||
{ 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: Exotic Elements (Floors 170–240) — 6 exotics + 2 convergence guards
|
||
// Original: Crystal, Stellar, Void (floors 170-200)
|
||
// New: Soul, Time, Plasma + a convergence guardian
|
||
// ═══════════════════════════════════════════════════════════════════════════════
|
||
|
||
const TIER3: Record<number, GuardianDef> = {
|
||
170: mk(170, '', ['crystal'], '#85C1E9', 0.35, 5.5,
|
||
[
|
||
{ type: 'elementalDamage', value: 20, desc: '+20% Crystal damage' },
|
||
{ type: 'maxMana', value: 300, desc: '+300 max mana' },
|
||
],
|
||
'Crystal spells reflect 15% damage back to attackers',
|
||
[{ type: 'reflect', value: 0.15 }],
|
||
{ shield: 2000, shieldRegen: 50, barrier: 0.10, barrierRegen: 0.03 },
|
||
),
|
||
180: mk(180, '', ['stellar'], '#F0E68C', 0.30, 6.0,
|
||
[
|
||
{ type: 'elementalDamage', value: 25, desc: '+25% Stellar damage' },
|
||
{ type: 'insightGain', value: 20, desc: '+20% insight gain' },
|
||
],
|
||
'Stellar spells deal +30% damage at night',
|
||
[{ type: 'night_bonus', value: 0.3 }],
|
||
{ barrier: 0.15, barrierRegen: 0.04, healthRegen: 8, healthRegenIsPercent: true },
|
||
),
|
||
190: mk(190, '', ['void'], '#4A235A', 0.35, 6.5,
|
||
[
|
||
{ type: 'elementalDamage', value: 25, desc: '+25% Void damage' },
|
||
{ type: 'rawDamage', value: 15, desc: '+15% raw damage' },
|
||
],
|
||
'Void spells ignore 40% of all resistances',
|
||
[{ 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'], '#E8D5F5', 0.35, 7.0,
|
||
[
|
||
{ type: 'elementalDamage', value: 30, desc: '+30% Exotic damage' },
|
||
{ type: 'maxMana', value: 400, desc: '+400 max mana' },
|
||
],
|
||
'Exotic convergence: Crystal/Stellar/Void spells bypass all defenses and shields',
|
||
[{ type: 'defense_pierce', value: 0.3 }, { type: 'resist_ignore', value: 0.2 }, { type: 'reflect', value: 0.1 }],
|
||
{ shield: 2800, shieldRegen: 55, barrier: 0.08, barrierRegen: 0.02 },
|
||
),
|
||
210: mk(210, '', ['soul', 'time', 'plasma'], '#C5B99A', 0.32, 7.5,
|
||
[
|
||
{ type: 'elementalDamage', value: 25, desc: '+25% Astral damage' },
|
||
{ type: 'castingSpeed', value: 20, desc: '+20% casting speed' },
|
||
],
|
||
'Astral convergence: Soul/Time/Plasma spells slow and pierce all defenses',
|
||
[{ type: 'defense_pierce', value: 0.3 }, { type: 'slow', value: 0.2 }, { type: 'chain', value: 2 }],
|
||
{ 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: 25, desc: '+25% Exotic damage' },
|
||
{ type: 'insightGain', value: 20, desc: '+20% insight gain' },
|
||
],
|
||
'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: 25, desc: '+25% Astral damage' },
|
||
{ type: 'spellEfficiency', value: 15, desc: '+15% spell efficiency' },
|
||
],
|
||
'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 },
|
||
),
|
||
};
|
||
|
||
// ═══════════════════════════════════════════════════════════════════════════════
|
||
// COMBINED STATIC GUARDIANS
|
||
// ═══════════════════════════════════════════════════════════════════════════════
|
||
|
||
const STATIC_GUARDIANS: Record<number, GuardianDef> = {
|
||
...TIER1,
|
||
...TIER2,
|
||
...TIER3,
|
||
};
|
||
|
||
export { STATIC_GUARDIANS, TIER1, TIER2, TIER3 };
|