refactor: remove skill system leftovers, migrate click mana to discipline perk
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m30s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m30s
- Simplified getMeditationBonus() to continuous ramp formula - Added click-mana capped perk to Mana Circulation discipline - Removed manaWell/manaFlow/manaSpring skill reads and prestige upgrades - Removed all skill fields from GameState and GameActionType - Updated all call sites and tests (916 tests passing) Closes #174
This commit is contained in:
@@ -10,7 +10,6 @@ import { BASE_GUARDIANS } from '../data/guardian-data';
|
||||
// ─── Damage Calculation Params ──────────────────────────────────────────────
|
||||
|
||||
export interface DamageCalcParams {
|
||||
skills: Record<string, number>;
|
||||
signedPacts: number[];
|
||||
}
|
||||
|
||||
@@ -21,13 +20,11 @@ export interface InsightCalcParams {
|
||||
totalManaGathered: number;
|
||||
signedPacts: number[];
|
||||
prestigeUpgrades: Record<string, number>;
|
||||
skills: Record<string, number>;
|
||||
}
|
||||
|
||||
// ─── DPS Calculation Params ─────────────────────────────────────────────────
|
||||
|
||||
export interface DPSCalcParams {
|
||||
skills: Record<string, number>;
|
||||
signedPacts: number[];
|
||||
equippedInstances: Record<string, string | null>;
|
||||
equipmentInstances: Record<string, EquipmentInstance>;
|
||||
@@ -150,24 +147,21 @@ export function calcDamage(
|
||||
): number {
|
||||
const sp = SPELLS_DEF[spellId];
|
||||
if (!sp) return 5;
|
||||
const skills = state.skills;
|
||||
|
||||
// Base damage: spell base + skill bonus + discipline bonus
|
||||
// Base damage: spell base + discipline bonus
|
||||
const discBaseDmg = discipline?.bonuses?.baseDamageBonus || 0;
|
||||
const baseDmg = sp.dmg + (skills.combatTrain || 0) * 5 + discBaseDmg;
|
||||
const baseDmg = sp.dmg + discBaseDmg;
|
||||
|
||||
// Percentage multiplier
|
||||
const discDmgMult = discipline?.bonuses?.baseDamageMultiplier || 0;
|
||||
const pct = 1 + (skills.arcaneFury || 0) * 0.1 + discDmgMult;
|
||||
const pct = 1 + discDmgMult;
|
||||
|
||||
// Elemental mastery bonus
|
||||
const elemMasteryBonus = 1 + (skills.elementalMastery || 0) * 0.15;
|
||||
const elemMasteryBonus = 1;
|
||||
|
||||
// Guardian bane bonus
|
||||
const isGuardianFloor = floorElem && Object.values(BASE_GUARDIANS).some(g => g.element === floorElem);
|
||||
const guardianBonus = isGuardianFloor
|
||||
? 1 + (skills.guardianBane || 0) * 0.2
|
||||
: 1;
|
||||
const guardianBonus = 1;
|
||||
|
||||
// Get boon bonuses from pacts
|
||||
const boons = getBoonBonuses(state.signedPacts);
|
||||
@@ -177,7 +171,7 @@ export function calcDamage(
|
||||
const elemDamageMult = 1 + boons.elementalDamage / 100;
|
||||
|
||||
// Apply crit chance and damage from boons
|
||||
const critChance = (skills.precision || 0) * 0.05 + boons.critChance / 100;
|
||||
const critChance = boons.critChance / 100;
|
||||
const critDamageMult = 1.5 + boons.critDamage / 100;
|
||||
|
||||
let damage = baseDmg * pct * elemMasteryBonus * guardianBonus * rawDamageMult * elemDamageMult;
|
||||
@@ -200,7 +194,7 @@ export function calcDamage(
|
||||
export function calcInsight(state: InsightCalcParams, discipline?: DisciplineBonuses): number {
|
||||
const pu = state.prestigeUpgrades;
|
||||
const discInsightBonus = discipline?.bonuses?.insightGainBonus || 0;
|
||||
const skillBonus = 1 + (state.skills.insightHarvest || 0) * 0.1 + discInsightBonus;
|
||||
const skillBonus = 1 + discInsightBonus;
|
||||
|
||||
// Get boon bonuses for insight gain
|
||||
const boons = getBoonBonuses(state.signedPacts);
|
||||
@@ -323,7 +317,7 @@ export function getTotalDPS(
|
||||
|
||||
// Get cast speed (spells per second)
|
||||
const baseCastTime = spellDef.baseCastTime || 1.0;
|
||||
const castingSpeedBonus = 1 + (state.skills.castingSpeed || 0) * 0.1;
|
||||
const castingSpeedBonus = 1;
|
||||
const equipmentAttackSpeed = upgradeEffects.attackSpeedMultiplier || 1;
|
||||
const castTime = baseCastTime / (castingSpeedBonus * equipmentAttackSpeed);
|
||||
|
||||
|
||||
@@ -13,10 +13,7 @@ export interface DisciplineBonuses {
|
||||
// ─── Mana Params ────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ManaComputeParams {
|
||||
skills?: Record<string, number>;
|
||||
prestigeUpgrades?: Record<string, number>;
|
||||
skillUpgrades?: Record<string, string[]>;
|
||||
skillTiers?: Record<string, number>;
|
||||
}
|
||||
|
||||
export interface RegenComputeParams extends ManaComputeParams {
|
||||
@@ -38,7 +35,6 @@ export function computeMaxMana(
|
||||
const pu = state.prestigeUpgrades || {};
|
||||
const base =
|
||||
100 +
|
||||
((state.skills || {}).manaWell || 0) * 100 +
|
||||
(pu.manaWell || 0) * 500 +
|
||||
(discipline?.bonuses?.maxManaBonus || 0);
|
||||
|
||||
@@ -51,7 +47,7 @@ export function computeMaxMana(
|
||||
// ─── Regen ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export function computeRegen(
|
||||
state: Pick<RegenComputeParams, 'skills' | 'prestigeUpgrades' | 'attunements'> & Partial<Pick<RegenComputeParams, 'skillUpgrades' | 'skillTiers'>>,
|
||||
state: Pick<RegenComputeParams, 'prestigeUpgrades' | 'attunements'>,
|
||||
effects?: ComputedEffects,
|
||||
discipline?: DisciplineBonuses,
|
||||
): number {
|
||||
@@ -59,8 +55,6 @@ export function computeRegen(
|
||||
const temporalBonus = 1 + (pu.temporalEcho || 0) * 0.1;
|
||||
const base =
|
||||
2 +
|
||||
((state.skills || {}).manaFlow || 0) * 1 +
|
||||
((state.skills || {}).manaSpring || 0) * 2 +
|
||||
((pu || {}).manaFlow || 0) * 0.5;
|
||||
|
||||
let regen = base * temporalBonus;
|
||||
@@ -85,7 +79,7 @@ export function computeRegen(
|
||||
// ─── Effective Regen for Display ──────────────────────────────────────────────
|
||||
|
||||
export function computeEffectiveRegenForDisplay(
|
||||
state: Pick<RegenComputeParams, 'skills' | 'prestigeUpgrades' | 'attunements'>,
|
||||
state: Pick<RegenComputeParams, 'prestigeUpgrades' | 'attunements'>,
|
||||
effects?: ComputedEffects,
|
||||
discipline?: DisciplineBonuses,
|
||||
): { rawRegen: number; conversionDrain: number; effectiveRegen: number } {
|
||||
@@ -99,7 +93,7 @@ export function computeEffectiveRegenForDisplay(
|
||||
// ─── Effective Regen (dynamic) ────────────────────────────────────────────────
|
||||
|
||||
export function computeEffectiveRegen(
|
||||
state: Pick<RegenComputeParams, 'skills' | 'prestigeUpgrades' | 'attunements'> & { rawMana: number; incursionStrength: number },
|
||||
state: Pick<RegenComputeParams, 'prestigeUpgrades' | 'attunements'> & { rawMana: number; incursionStrength: number },
|
||||
effects?: ComputedEffects,
|
||||
discipline?: DisciplineBonuses,
|
||||
): number {
|
||||
@@ -112,56 +106,25 @@ export function computeEffectiveRegen(
|
||||
// ─── Click Mana ───────────────────────────────────────────────────────────────
|
||||
|
||||
export function computeClickMana(
|
||||
skills: Record<string, number>,
|
||||
discipline?: DisciplineBonuses,
|
||||
): number {
|
||||
const skillTap = (skills.manaTap || 0) * 1;
|
||||
const skillSurge = (skills.manaSurge || 0) * 3;
|
||||
const discClickMult = discipline?.bonuses?.clickManaMultiplier || 0;
|
||||
|
||||
return 1 + skillTap + skillSurge + discClickMult;
|
||||
const discClickBonus = discipline?.bonuses?.clickManaBonus || 0;
|
||||
return 1 + discClickBonus;
|
||||
}
|
||||
|
||||
// ─── Meditation Bonus ─────────────────────────────────────────────────────────
|
||||
|
||||
export function getMeditationBonus(
|
||||
meditateTicks: number,
|
||||
skills: Record<string, number>,
|
||||
meditationEfficiency: number = 1,
|
||||
disciplineMeditationCap: number = 0,
|
||||
): number {
|
||||
const hasMeditation = skills.meditation === 1;
|
||||
const hasDeepTrance = skills.deepTrance === 1;
|
||||
const hasVoidMeditation = skills.voidMeditation === 1;
|
||||
|
||||
const hours = meditateTicks * HOURS_PER_TICK;
|
||||
|
||||
// Determine the hard cap for this meditation session.
|
||||
// disciplineMeditationCap adds +0.5 per point (e.g. from Mana Circulation discipline).
|
||||
// Base max is 5.0 (Void Meditation), each discipline bonus adds +0.5.
|
||||
// Continuous ramp: 1 + (hours / 8) * 4, capped at 5.0 + disciplineMeditationCap
|
||||
const maxMultiplier = 5.0 + disciplineMeditationCap;
|
||||
|
||||
// Base meditation: ramps up over 4 hours, capped at 1.5x or discipline cap
|
||||
let bonus = 1 + Math.min(hours / 4, 0.5);
|
||||
bonus = Math.min(bonus, maxMultiplier);
|
||||
|
||||
// With Meditation Focus: up to 2.5x after 4 hours
|
||||
if (hasMeditation && hours >= 4) {
|
||||
bonus = Math.min(2.5, maxMultiplier);
|
||||
}
|
||||
|
||||
// With Deep Trance: up to 3.0x after 6 hours
|
||||
if (hasDeepTrance && hours >= 6) {
|
||||
bonus = Math.min(3.0, maxMultiplier);
|
||||
}
|
||||
|
||||
// With Void Meditation: up to maxMultiplier after 8 hours
|
||||
if (hasVoidMeditation && hours >= 8) {
|
||||
bonus = maxMultiplier;
|
||||
}
|
||||
const bonus = Math.min(1 + (hours / 8) * 4, maxMultiplier);
|
||||
|
||||
// Apply meditation efficiency from upgrades
|
||||
bonus *= meditationEfficiency;
|
||||
|
||||
return bonus;
|
||||
return bonus * meditationEfficiency;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user