fix: spire combat 11 high-severity discrepancies (issue #333)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
D-01: Implement per-weapon cast progress (weaponCastProgress record) D-04: Bypass Executioner/Berserker discipline specials for golem attacks D-09: Fix lightning counter direction (lightning→water, not lightning→earth) D-10: Add full composite element counters (blackflame/radiantflames ↔ frost/water/light/dark) D-15: Fix Executioner to check per-enemy HP < 25% instead of floorHP ratio D-20: Fix dodge formula to match spec (min(0.55, floor × 0.003), starts at 0) D-22: Fix shield modifier to use flat HP pool instead of percentage barrier D-23: Wire up applyMageBarrierRecharge in the damage pipeline D-25: Move guardian regen from per-damage-event to once-per-tick D-26: Add guardian armor reduction to the guardian defensive pipeline D-31: Fix armor_corrode to be temporary (restore armor on effect expiry) D-38: Implement AoE damage distribution across enemies All 1069 tests pass. No files exceed 400 lines.
This commit is contained in:
@@ -33,19 +33,20 @@ export interface DPSCalcParams {
|
||||
}
|
||||
|
||||
// ─── Elemental Damage Bonus ──────────────────────────────────────────────────
|
||||
|
||||
// Elemental damage bonus: +50% if spell element opposes floor element (super effective)
|
||||
// +50% if spell element opposes floor element (super effective)
|
||||
// -25% if spell element matches its own opposite (weak)
|
||||
export function getElementalBonus(spellElem: string, floorElem: string): number {
|
||||
if (spellElem === 'raw') return 1.0; // Raw mana has no elemental bonus
|
||||
|
||||
if (spellElem === floorElem) return 1.25; // Same element: +25% damage
|
||||
|
||||
// Check for super effective first: spell is the opposite of floor
|
||||
if (ELEMENT_OPPOSITES[floorElem] === spellElem) return 1.5; // Super effective: +50% damage
|
||||
// Check for super effective: spellElem is in floorElem's opposites list
|
||||
const floorOpposites = ELEMENT_OPPOSITES[floorElem];
|
||||
if (floorOpposites && floorOpposites.includes(spellElem)) return 1.5; // Super effective: +50% damage
|
||||
|
||||
// Check for weak: spell's opposite matches floor
|
||||
if (ELEMENT_OPPOSITES[spellElem] === floorElem) return 0.75; // Weak: -25% damage
|
||||
// Check for weak: floorElem is in spellElem's opposites list
|
||||
const spellOpposites = ELEMENT_OPPOSITES[spellElem];
|
||||
if (spellOpposites && spellOpposites.includes(floorElem)) return 0.75; // Weak: -25% damage
|
||||
|
||||
return 1.0; // Neutral
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const MODIFIER_CONFIG = {
|
||||
barrierRechargeRate: 0.05, // Recharges 5% of max HP per tick
|
||||
},
|
||||
shield: {
|
||||
shieldAmount: 0.15, // 15% of max HP as one-time shield
|
||||
shieldAmount: 0.15, // 15% of max HP as one-time flat shield pool (spec §5.1)
|
||||
},
|
||||
armored: {
|
||||
armorPerFloor: 0.003,
|
||||
@@ -37,8 +37,8 @@ const MODIFIER_CONFIG = {
|
||||
armorPerFloor: 0.002,
|
||||
},
|
||||
agile: {
|
||||
baseDodge: 0.20,
|
||||
dodgePerFloor: 0.004,
|
||||
baseDodge: 0,
|
||||
dodgePerFloor: 0.003,
|
||||
maxDodge: 0.55,
|
||||
},
|
||||
};
|
||||
@@ -126,10 +126,11 @@ export function generateEnemy(floor: number, modifiers?: EnemyModifier[]): Gener
|
||||
}
|
||||
|
||||
if (activeModifiers.includes('shield')) {
|
||||
barrier = Math.max(barrier, MODIFIER_CONFIG.shield.shieldAmount);
|
||||
name = `${name} (Shielded)`;
|
||||
}
|
||||
|
||||
const shieldPool = activeModifiers.includes('shield') ? hp * MODIFIER_CONFIG.shield.shieldAmount : 0;
|
||||
|
||||
return {
|
||||
id: 'enemy',
|
||||
name,
|
||||
@@ -138,7 +139,10 @@ export function generateEnemy(floor: number, modifiers?: EnemyModifier[]): Gener
|
||||
armor,
|
||||
dodgeChance,
|
||||
barrier,
|
||||
shieldPool,
|
||||
element,
|
||||
activeEffects: [],
|
||||
effectiveArmor: armor,
|
||||
modifiers: activeModifiers,
|
||||
};
|
||||
}
|
||||
@@ -172,6 +176,8 @@ export function generateSwarm(floor: number, modifiers?: EnemyModifier[]): Gener
|
||||
: 0,
|
||||
barrier: 0,
|
||||
element,
|
||||
activeEffects: [],
|
||||
effectiveArmor: armor,
|
||||
modifiers: activeModifiers,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user