feat(combat): Add pre-battle strike resolution for commanders
- Extend `CombatEngine._resolvePreBattleSkills` to capture `strike` and `strike-all` skills from commanders during the `preBattle` phase. - Introduce `strikeFires` to track strike hits, including damage, targets, and commander status. - Update `BattleScene._processPreBattleSequence` to handle and animate `strikeFires` alongside other pre-battle effects. - Ensure death events are correctly processed for non-commander targets destroyed by pre-battle strikes.
This commit is contained in:
parent
313f14b956
commit
547196f709
|
|
@ -546,13 +546,16 @@ export class CombatEngine {
|
||||||
const sanctifyFires = [];
|
const sanctifyFires = [];
|
||||||
const overchargeFires = [];
|
const overchargeFires = [];
|
||||||
const fortifyFires = [];
|
const fortifyFires = [];
|
||||||
|
const strikeFires = [];
|
||||||
const liveAllies = allies.filter(c => c.currentHP > 0);
|
const liveAllies = allies.filter(c => c.currentHP > 0);
|
||||||
const liveEnemies = enemies.filter(c => c.currentHP > 0);
|
const liveEnemies = enemies.filter(c => c.currentHP > 0);
|
||||||
for (const card of cards) {
|
for (const card of cards) {
|
||||||
if (card.currentHP <= 0) continue;
|
if (card.currentHP <= 0) continue;
|
||||||
if (card.currentDelay > 0) continue;
|
if (card.currentDelay > 0) continue;
|
||||||
for (const s of card.skills) {
|
for (const s of card.skills) {
|
||||||
if (s.trigger !== 'preBattle') continue;
|
// Commanders fire their strike/strike-all during preBattle instead of preAttack
|
||||||
|
const isCommanderStrike = card.type === 'commander' && s.name === 'strike' && s.trigger === 'preAttack';
|
||||||
|
if (s.trigger !== 'preBattle' && !isCommanderStrike) continue;
|
||||||
// For drain, resolve the card directly across as defender
|
// For drain, resolve the card directly across as defender
|
||||||
const cardIdx = cards.indexOf(card);
|
const cardIdx = cards.indexOf(card);
|
||||||
const acrossCard = enemyLanes[cardIdx];
|
const acrossCard = enemyLanes[cardIdx];
|
||||||
|
|
@ -676,9 +679,36 @@ export class CombatEngine {
|
||||||
fortifyFires.push({ skill: 'fortify', source: card, target: ctx.fortifyTarget, amount: ctx.fortifyAmount });
|
fortifyFires.push({ skill: 'fortify', source: card, target: ctx.fortifyTarget, amount: ctx.fortifyAmount });
|
||||||
this._log(`${card.name} fortify: +${ctx.fortifyAmount} ARM to self`);
|
this._log(`${card.name} fortify: +${ctx.fortifyAmount} ARM to self`);
|
||||||
}
|
}
|
||||||
|
if (s.name === 'strike' && ctx.strikeAllTargets) {
|
||||||
|
const isPlayerCard = this.playerLanes.includes(card) || card === this.playerCommander;
|
||||||
|
for (const t of ctx.strikeAllTargets) {
|
||||||
|
const targetIsCommander = t.target === enemyCommander;
|
||||||
|
strikeFires.push({ skill: 'strike', source: card, target: t.target, damage: t.damage, hpBefore: t.hpBefore, targetIsCommander, isAll: true });
|
||||||
|
this._log(`${card.name} strike all hits ${t.target.name} for ${t.damage}`);
|
||||||
|
if (!targetIsCommander && t.target.currentHP <= 0) {
|
||||||
|
this._log(`${t.target.name} is destroyed by strike all`);
|
||||||
|
const deadSide = isPlayerCard ? 'opponent' : 'player';
|
||||||
|
const deadAllies = isPlayerCard ? this.opponentLanes : this.playerLanes;
|
||||||
|
this.events.push({ type: 'death', card: t.target, side: deadSide });
|
||||||
|
this._processOnDeath(t.target, deadAllies, deadSide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (s.name === 'strike' && ctx.strikeTarget) {
|
||||||
|
const isPlayerCard = this.playerLanes.includes(card) || card === this.playerCommander;
|
||||||
|
const targetIsCommander = ctx.strikeTarget === enemyCommander;
|
||||||
|
strikeFires.push({ skill: 'strike', source: card, target: ctx.strikeTarget, damage: ctx.strikeDamage, hpBefore: ctx.strikeTarget.currentHP + ctx.strikeDamage, targetIsCommander });
|
||||||
|
this._log(`${card.name} strike hits ${ctx.strikeTarget.name} for ${ctx.strikeDamage}`);
|
||||||
|
if (!targetIsCommander && ctx.strikeTarget.currentHP <= 0) {
|
||||||
|
this._log(`${ctx.strikeTarget.name} is destroyed by strike`);
|
||||||
|
const deadSide = isPlayerCard ? 'opponent' : 'player';
|
||||||
|
const deadAllies = isPlayerCard ? this.opponentLanes : this.playerLanes;
|
||||||
|
this.events.push({ type: 'death', card: ctx.strikeTarget, side: deadSide });
|
||||||
|
this._processOnDeath(ctx.strikeTarget, deadAllies, deadSide);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { buffs, siegeFires, protectFires, enfeebeFires, jamFires, weakenFires, drainFires, healFires, sanctifyFires, overchargeFires, fortifyFires };
|
return { buffs, siegeFires, protectFires, enfeebeFires, jamFires, weakenFires, drainFires, healFires, sanctifyFires, overchargeFires, fortifyFires, strikeFires };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the 8-step pre-battle sequence and process preBattle skills.
|
// Emit the 8-step pre-battle sequence and process preBattle skills.
|
||||||
|
|
|
||||||
|
|
@ -2260,19 +2260,22 @@ export class BattleScene extends Phaser.Scene {
|
||||||
const hasSanctify = event.sanctifyFires?.length > 0;
|
const hasSanctify = event.sanctifyFires?.length > 0;
|
||||||
const hasOvercharge = event.overchargeFires?.length > 0;
|
const hasOvercharge = event.overchargeFires?.length > 0;
|
||||||
const hasFortify = event.fortifyFires?.length > 0;
|
const hasFortify = event.fortifyFires?.length > 0;
|
||||||
|
const hasStrike = event.strikeFires?.length > 0;
|
||||||
|
|
||||||
if (hasBuffs || hasSiege || hasProtect || hasEnfeeble || hasJam || hasWeaken || hasDrain || hasHeal || hasSanctify || hasOvercharge || hasFortify) {
|
if (hasBuffs || hasSiege || hasProtect || hasEnfeeble || hasJam || hasWeaken || hasDrain || hasHeal || hasSanctify || hasOvercharge || hasFortify || hasStrike) {
|
||||||
this._processSanctifyFires(event.sanctifyFires || [], () => {
|
this._processSanctifyFires(event.sanctifyFires || [], () => {
|
||||||
this._processDrainFires(event.drainFires || [], () => {
|
this._processDrainFires(event.drainFires || [], () => {
|
||||||
this._processOverchargeFires(event.overchargeFires || [], () => {
|
this._processOverchargeFires(event.overchargeFires || [], () => {
|
||||||
this._processBuffAnimations(event.buffs || [], () => {
|
this._processBuffAnimations(event.buffs || [], () => {
|
||||||
this._processFortifyFires(event.fortifyFires || [], () => {
|
this._processFortifyFires(event.fortifyFires || [], () => {
|
||||||
this._processSiegeFires(event.siegeFires || [], () => {
|
this._processSiegeFires(event.siegeFires || [], () => {
|
||||||
this._processProtectFires(event.protectFires || [], () => {
|
this._processPreBattleStrikeFires(event.strikeFires || [], () => {
|
||||||
this._processEnfeebeFires(event.enfeebeFires || [], () => {
|
this._processProtectFires(event.protectFires || [], () => {
|
||||||
this._processJamFires(event.jamFires || [], () => {
|
this._processEnfeebeFires(event.enfeebeFires || [], () => {
|
||||||
this._processWeakenFires(event.weakenFires || [], () => {
|
this._processJamFires(event.jamFires || [], () => {
|
||||||
this._processHealFires(event.healFires || [], onComplete);
|
this._processWeakenFires(event.weakenFires || [], () => {
|
||||||
|
this._processHealFires(event.healFires || [], onComplete);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -2288,6 +2291,15 @@ export class BattleScene extends Phaser.Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_processPreBattleStrikeFires(fires, onComplete) {
|
||||||
|
const next = (idx) => {
|
||||||
|
if (idx >= fires.length) { onComplete(); return; }
|
||||||
|
const fire = fires[idx];
|
||||||
|
this._animateStrikeFire(fire.source, fire, () => next(idx + 1));
|
||||||
|
};
|
||||||
|
next(0);
|
||||||
|
}
|
||||||
|
|
||||||
_processSiegeFires(fires, onComplete) {
|
_processSiegeFires(fires, onComplete) {
|
||||||
const next = (idx) => {
|
const next = (idx) => {
|
||||||
if (idx >= fires.length) { onComplete(); return; }
|
if (idx >= fires.length) { onComplete(); return; }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue