fix: defensive hardening — NaN guards, cast loop safety, discipline reset on new loop, spire mode maxFloorReached fix
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m20s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m20s
This commit is contained in:
@@ -87,8 +87,10 @@ export function processCombatTick(
|
||||
let currentFloor = state.currentFloor;
|
||||
let floorMaxHP = state.floorMaxHP;
|
||||
|
||||
// Process complete casts for active spell
|
||||
while (castProgress >= 1 && canAffordSpellCost(spellDef.cost, rawMana, elements)) {
|
||||
// Process complete casts for active spell (safety counter prevents infinite loop)
|
||||
let safetyCounter = 0;
|
||||
const MAX_CASTS_PER_TICK = 100;
|
||||
while (castProgress >= 1 && canAffordSpellCost(spellDef.cost, rawMana, elements) && safetyCounter < MAX_CASTS_PER_TICK) {
|
||||
// Deduct spell cost
|
||||
const afterCost = deductSpellCost(spellDef.cost, rawMana, elements);
|
||||
rawMana = afterCost.rawMana;
|
||||
@@ -108,9 +110,16 @@ export function processCombatTick(
|
||||
elements = result.elements;
|
||||
const finalDamage = result.modifiedDamage || damage;
|
||||
|
||||
// Guard against NaN damage — if damage is not finite, stop processing
|
||||
if (!Number.isFinite(finalDamage)) {
|
||||
logMessages.push('⚠️ Combat stopped: invalid damage value');
|
||||
break;
|
||||
}
|
||||
|
||||
// Apply damage
|
||||
floorHP = Math.max(0, floorHP - finalDamage);
|
||||
castProgress -= 1;
|
||||
safetyCounter++;
|
||||
|
||||
// Check if floor is cleared
|
||||
if (floorHP <= 0) {
|
||||
@@ -142,8 +151,10 @@ export function processCombatTick(
|
||||
const eProgressPerTick = HOURS_PER_TICK * eSpellCastSpeed * totalAttackSpeed;
|
||||
let eCastProgress = (eSpell.castProgress || 0) + eProgressPerTick;
|
||||
|
||||
// Process complete casts for equipment spells
|
||||
while (eCastProgress >= 1 && canAffordSpellCost(eSpellDef.cost, rawMana, elements)) {
|
||||
// Process complete casts for equipment spells (safety counter prevents infinite loop)
|
||||
let eSafetyCounter = 0;
|
||||
const MAX_E_CASTS_PER_TICK = 100;
|
||||
while (eCastProgress >= 1 && canAffordSpellCost(eSpellDef.cost, rawMana, elements) && eSafetyCounter < MAX_E_CASTS_PER_TICK) {
|
||||
// Deduct cost
|
||||
const eAfterCost = deductSpellCost(eSpellDef.cost, rawMana, elements);
|
||||
rawMana = eAfterCost.rawMana;
|
||||
@@ -162,8 +173,14 @@ export function processCombatTick(
|
||||
elements = eResult.elements;
|
||||
const eFinalDamage = eResult.modifiedDamage || eDamage;
|
||||
|
||||
// Guard against NaN damage
|
||||
if (!Number.isFinite(eFinalDamage)) {
|
||||
break;
|
||||
}
|
||||
|
||||
floorHP = Math.max(0, floorHP - eFinalDamage);
|
||||
eCastProgress -= 1;
|
||||
eSafetyCounter++;
|
||||
|
||||
if (floorHP <= 0) break; // Floor cleared, stop processing
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user