fix: issues #221 #217 #225 #227 #224 #226 - crafting refunds, mana tracking, cancel slot, multi-element guardians, spell kill advance
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m59s

This commit is contained in:
2026-05-31 01:18:01 +02:00
parent e4f4b297e8
commit 6793461a9f
16 changed files with 263 additions and 63 deletions
+34 -9
View File
@@ -6,7 +6,7 @@ import { SPELLS_DEF, HOURS_PER_TICK } from '../constants';
import { getGuardianForFloor } from '../data/guardian-encounters';
import type { CombatStore, CombatState } from './combat-state.types';
import type { SpellState } from '../types';
import { getFloorMaxHP, getFloorElement, calcDamage, canAffordSpellCost, deductSpellCost } from '../utils';
import { getFloorMaxHP, getFloorElement, getMultiElementBonus, calcDamage, canAffordSpellCost, deductSpellCost } from '../utils';
import { computeDisciplineEffects } from '../effects/discipline-effects';
/**
@@ -95,14 +95,21 @@ export function processCombatTick(
const afterCost = deductSpellCost(spellDef.cost, rawMana, elements);
rawMana = afterCost.rawMana;
elements = afterCost.elements;
// Calculate base damage
// Calculate base damage (without elemental bonus first)
const floorElement = getFloorElement(currentFloor);
const damage = calcDamage(
const baseDamage = calcDamage(
{ signedPacts },
spellId,
floorElement,
undefined,
disciplineEffects,
);
// Apply elemental bonus — for multi-element guardians, use all elements
const guardian = getGuardianForFloor(currentFloor);
const floorElems = guardian && guardian.element.length > 0
? guardian.element
: [floorElement];
const multiElemBonus = getMultiElementBonus(spellDef.elem, floorElems);
const damage = baseDamage * multiElemBonus;
// Let gameStore apply damage modifiers (executioner, berserker)
const result = onDamageDealt(damage);
@@ -125,7 +132,6 @@ export function processCombatTick(
if (floorHP <= 0) {
const guardian = getGuardianForFloor(currentFloor);
onFloorCleared(currentFloor, !!guardian);
currentFloor = Math.min(currentFloor + 1, 100);
floorMaxHP = getFloorMaxHP(currentFloor);
floorHP = floorMaxHP;
@@ -159,14 +165,20 @@ export function processCombatTick(
const eAfterCost = deductSpellCost(eSpellDef.cost, rawMana, elements);
rawMana = eAfterCost.rawMana;
elements = eAfterCost.elements;
// Calculate damage
// Calculate damage — for multi-element guardians, use all elements
const eFloorElement = getFloorElement(currentFloor);
const eDamage = calcDamage(
const eBaseDamage = calcDamage(
{ signedPacts },
eSpell.spellId,
eFloorElement,
undefined,
disciplineEffects,
);
const eGuardian = getGuardianForFloor(currentFloor);
const eFloorElems = eGuardian && eGuardian.element.length > 0
? eGuardian.element
: [eFloorElement];
const eMultiElemBonus = getMultiElementBonus(eSpellDef.elem, eFloorElems);
const eDamage = eBaseDamage * eMultiElemBonus;
const eResult = onDamageDealt(eDamage);
rawMana = eResult.rawMana;
@@ -182,7 +194,20 @@ export function processCombatTick(
eCastProgress -= 1;
eSafetyCounter++;
if (floorHP <= 0) break; // Floor cleared, stop processing
if (floorHP <= 0) {
const eGuardian = getGuardianForFloor(currentFloor);
onFloorCleared(currentFloor, !!eGuardian);
currentFloor = Math.min(currentFloor + 1, 100);
floorMaxHP = getFloorMaxHP(currentFloor);
floorHP = floorMaxHP;
eCastProgress = 0;
if (eGuardian) {
logMessages.push(`\u2694\ufe0f ${eGuardian.name} defeated!`);
} else if (currentFloor % 5 === 0) {
logMessages.push(`🏰 Floor ${currentFloor - 1} cleared!`);
}
break;
}
}
// Update equipment spell state