167 lines
5.9 KiB
JavaScript
167 lines
5.9 KiB
JavaScript
export class SkillProcessor {
|
|
constructor() {}
|
|
|
|
process(skill, attacker, defender, allies, enemies, context = {}) {
|
|
const handler = this[skill.name];
|
|
if (handler) handler.call(this, skill, attacker, defender, allies, enemies, context);
|
|
}
|
|
|
|
strike(skill, attacker, defender, allies, enemies, context) {
|
|
const target = defender || context?.enemyCommander;
|
|
if (!target) return;
|
|
const dmg = Math.max(0, skill.value - Math.max(0, target.currentArmor));
|
|
target.currentHP -= dmg;
|
|
attacker._lastSkillDmg = (attacker._lastSkillDmg || 0) + dmg;
|
|
if (context) {
|
|
context.strikeTarget = target;
|
|
context.strikeDamage = dmg;
|
|
}
|
|
}
|
|
|
|
swipe(skill, attacker, defender, allies, enemies) {
|
|
const baseDmg = attacker.currentAttack + skill.value;
|
|
for (const enemy of enemies) {
|
|
const dmg = Math.max(0, baseDmg - Math.max(0, enemy.currentArmor));
|
|
enemy.currentHP -= dmg;
|
|
}
|
|
}
|
|
|
|
pierce(skill, attacker, defender, allies, enemies, context) {
|
|
if (!defender) return;
|
|
context.pierceBonus = (context.pierceBonus || 0) + skill.value;
|
|
}
|
|
|
|
rupture(skill, attacker, defender) {
|
|
if (!defender) return;
|
|
defender.ruptureStacks = (defender.ruptureStacks || 0) + skill.value;
|
|
}
|
|
|
|
berserk(skill, attacker, defender, allies, enemies, context) {
|
|
if (context.trigger === 'on_attack' && context.damageDealt > 0) {
|
|
attacker.currentAttack += skill.value;
|
|
}
|
|
}
|
|
|
|
siege(skill, attacker, defender, allies, enemies, context) {
|
|
if (context.enemyCommander) {
|
|
const dmg = Math.max(0, skill.value - Math.max(0, context.enemyCommander.currentArmor));
|
|
context.enemyCommander.currentHP -= dmg;
|
|
}
|
|
}
|
|
|
|
rally(skill, attacker, defender, allies, enemies, context) {
|
|
const assaultAllies = allies.filter(a => a.type === 'assault' && a !== attacker && a.currentHP > 0);
|
|
if (assaultAllies.length === 0) return;
|
|
const rng = context?.rng;
|
|
const idx = rng
|
|
? rng.nextInt(0, assaultAllies.length - 1)
|
|
: Math.floor(Math.random() * assaultAllies.length);
|
|
const target = assaultAllies[idx];
|
|
target.currentAttack += skill.value;
|
|
// Track temp buff so postBattle can reverse it
|
|
target._tempBuffs = target._tempBuffs || [];
|
|
target._tempBuffs.push({ stat: 'currentAttack', amount: skill.value, source: 'rally' });
|
|
// Expose to caller for event / animation data
|
|
context.rallyTarget = target;
|
|
}
|
|
|
|
heal(skill, attacker, defender, allies) {
|
|
const damaged = allies
|
|
.filter(a => a.currentHP > 0 && a.currentHP < a.health)
|
|
.sort((a, b) => (a.currentHP / a.health) - (b.currentHP / b.health));
|
|
if (damaged.length === 0) return;
|
|
damaged[0].currentHP = Math.min(damaged[0].health, damaged[0].currentHP + skill.value);
|
|
}
|
|
|
|
protect(skill, attacker, defender, allies) {
|
|
const alive = allies.filter(a => a.currentHP > 0 && a !== attacker);
|
|
if (alive.length === 0) return;
|
|
const target = alive[Math.floor(Math.random() * alive.length)];
|
|
target.currentArmor += skill.value;
|
|
}
|
|
|
|
jam(skill, attacker, defender) {
|
|
if (!defender) return;
|
|
defender.jamTurns = (defender.jamTurns || 0) + skill.value;
|
|
}
|
|
|
|
enfeeble(skill, attacker, defender) {
|
|
if (!defender) return;
|
|
defender.currentAttack = Math.max(0, defender.currentAttack - skill.value);
|
|
}
|
|
|
|
weaken(skill, attacker, defender) {
|
|
if (!defender) return;
|
|
for (const s of defender.skills) {
|
|
s.value = Math.max(0, (s.value || 0) - skill.value);
|
|
}
|
|
}
|
|
|
|
tribute(skill, attacker, defender, allies, enemies, context) {
|
|
// Destroy weakest ally for +3 attack to attacker
|
|
const weakest = allies
|
|
.filter(a => a !== attacker && a.type === 'assault' && a.currentHP > 0)
|
|
.sort((a, b) => a.currentHP - b.currentHP)[0];
|
|
if (weakest) {
|
|
weakest.currentHP = 0;
|
|
attacker.currentAttack += 3;
|
|
}
|
|
}
|
|
|
|
evolve(skill, attacker, defender, allies, enemies, context) {
|
|
// Evolve to upgraded version — check for evolved card id convention: id + '_e'
|
|
const evolvedId = attacker.id + '_e';
|
|
if (context.cardManager && context.cardManager.getCard(evolvedId)) {
|
|
const evolved = context.cardManager.createInstance(evolvedId);
|
|
evolved.currentHP = attacker.currentHP;
|
|
evolved.instanceId = attacker.instanceId;
|
|
Object.assign(attacker, evolved);
|
|
}
|
|
}
|
|
|
|
mortar(skill, attacker, defender, allies, enemies, context) {
|
|
if (enemies.length === 0) return;
|
|
const rng = context?.rng;
|
|
const idx = rng ? rng.nextInt(0, enemies.length - 1) : Math.floor(Math.random() * enemies.length);
|
|
const target = enemies[idx];
|
|
const dmg = Math.max(0, skill.value - Math.max(0, target.currentArmor));
|
|
target.currentHP -= dmg;
|
|
if (context) {
|
|
context.mortarTarget = target;
|
|
context.mortarDamage = dmg;
|
|
}
|
|
}
|
|
|
|
flurry(skill, attacker, defender, allies, enemies, context) {
|
|
context.extraAttacks = (context.extraAttacks || 0) + skill.value;
|
|
}
|
|
|
|
counter(skill, attacker, defender, allies, enemies, context) {
|
|
// When defending — deal counter damage to attacker
|
|
if (context.attackingCard) {
|
|
const dmg = Math.max(0, skill.value - Math.max(0, context.attackingCard.currentArmor));
|
|
context.attackingCard.currentHP -= dmg;
|
|
}
|
|
}
|
|
|
|
wall(skill, attacker, defender, allies, enemies, context) {
|
|
context.damageAbsorb = (context.damageAbsorb || 0) + skill.value;
|
|
}
|
|
|
|
armored(skill, attacker, defender, allies, enemies, context) {
|
|
// Passive: reduce incoming damage — handled in combat engine when applying damage
|
|
context.armoredBonus = (context.armoredBonus || 0) + skill.value;
|
|
}
|
|
|
|
valor(skill, attacker, defender, allies, enemies) {
|
|
if (enemies.length > allies.length) {
|
|
attacker.currentAttack += skill.value;
|
|
}
|
|
}
|
|
|
|
legion(skill, attacker, defender, allies) {
|
|
const sameFaction = allies.filter(a => a.faction === attacker.faction && a !== attacker && a.currentHP > 0);
|
|
attacker.currentAttack += skill.value * sameFaction.length;
|
|
}
|
|
}
|