feat: implement sword/melee auto-attack system (spec §3.1, §4.3)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m1s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m1s
- Add calcMeleeDamage() with elemental matchup for enchanted swords - Add meleeSwordProgress per-instance accumulator to combat state - Add melee branch in processCombatTick (no mana cost, no Executioner/Berserker) - Add baseDamage/attackSpeed stats to all 5 sword types - Wire equippedSwords through gameStore to combat tick pipeline - 16 new regression tests, all 937 tests pass
This commit is contained in:
@@ -273,6 +273,55 @@ export function deductSpellCost(
|
||||
return { rawMana, elements: newElements };
|
||||
}
|
||||
|
||||
// ─── Melee Damage Calculation (spec §4.3) ────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Map from sword enchantment specialId to element type for elemental matchup.
|
||||
*/
|
||||
const SWORD_ENCHANT_ELEMENT: Record<string, string> = {
|
||||
fireBlade: 'fire',
|
||||
frostBlade: 'frost',
|
||||
lightningBlade: 'lightning',
|
||||
voidBlade: 'void',
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate melee damage for a sword attack (spec §4.3).
|
||||
*
|
||||
* Formula: baseDmg = sword.baseDamage + sword.elementalEnchantDamage
|
||||
* damage = baseDmg × getElementalBonus(sword.enchantElement, enemy.element)
|
||||
*
|
||||
* No crit, no discipline damage bonus for melee in v1.
|
||||
* attackSpeedMult from equipment does apply to meleeProgress accumulation.
|
||||
*/
|
||||
export function calcMeleeDamage(
|
||||
swordInstance: EquipmentInstance,
|
||||
swordType: { stats?: { baseDamage?: number } },
|
||||
enemyElement: string,
|
||||
): number {
|
||||
const baseDmg = swordType.stats?.baseDamage || 5;
|
||||
|
||||
// Determine enchant element from sword's enchantments
|
||||
let enchantElement: string | null = null;
|
||||
for (const ench of swordInstance.enchantments) {
|
||||
const effectDef = ENCHANTMENT_EFFECTS[ench.effectId];
|
||||
if (effectDef?.effect.type === 'special' && effectDef.effect.specialId) {
|
||||
const elem = SWORD_ENCHANT_ELEMENT[effectDef.effect.specialId];
|
||||
if (elem) {
|
||||
enchantElement = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply elemental bonus if sword has an elemental enchant
|
||||
if (enchantElement) {
|
||||
return baseDmg * getElementalBonus(enchantElement, enemyElement);
|
||||
}
|
||||
|
||||
return baseDmg;
|
||||
}
|
||||
|
||||
// ─── Equipment Spell Helpers ──────────────────────────────────────────────────
|
||||
|
||||
// Return type for active equipment spells with source equipment
|
||||
|
||||
Reference in New Issue
Block a user