feat: implement smite skill, rework enfeeble to hive_link/wound, update card skills and flavor texts

- Add 'smite' damage-over-time skill with single/all-target support and animation
- Rename 'enfeeble' to 'hive_link' on xeno cards; add persistent ATK gain on death
- Replace some enfeeble instances with new 'wound' skill (applied on_attack)
- Adjust cleanse trigger from preBattle to postBattle, reduce values
- Rebalance overcharge/fortify/heal/smite skill distributions across factions
- Update all card flavor texts for thematic consistency and personality
- Fix wound badge positioning and origin in CardObject display
- Speed up strike/smite animations (2000→500ms, 500→250ms, etc.)
- Add smiteFires to pre-battle event flow with restore/reapply logic
This commit is contained in:
Brian Fertig 2026-04-04 09:26:01 -06:00
parent d98070915f
commit 0a76d7352b
7 changed files with 194 additions and 87 deletions

Binary file not shown.

View File

@ -165,7 +165,7 @@
] ]
} }
], ],
"flavorText": "The Centurion's armor has never been breached. Neither has his line.", "flavorText": "Hold the line for the Emperor! I will defend thee!",
"artKey": "imp_cmd_2" "artKey": "imp_cmd_2"
}, },
{ {
@ -250,7 +250,7 @@
] ]
} }
], ],
"flavorText": "She does not command retreat. She commands annihilation.", "flavorText": "I must defend the empire's glory, no matter the cost!",
"artKey": "imp_cmd_3" "artKey": "imp_cmd_3"
}, },
{ {
@ -267,10 +267,9 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "enfeeble", "name": "hive_link",
"value": 1, "value": 1,
"all": true, "all": true
"trigger": "preBattle"
} }
] ]
}, },
@ -281,10 +280,9 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "enfeeble", "name": "hive_link",
"value": 2, "value": 2,
"all": true, "all": true
"trigger": "preBattle"
} }
] ]
}, },
@ -301,10 +299,9 @@
"trigger": "postBattle" "trigger": "postBattle"
}, },
{ {
"name": "enfeeble", "name": "hive_link",
"value": 3, "value": 3,
"all": true, "all": true
"trigger": "preBattle"
} }
] ]
}, },
@ -316,15 +313,14 @@
"skills": [ "skills": [
{ {
"name": "cleanse", "name": "cleanse",
"value": 9, "value": 8,
"all": true, "all": true,
"trigger": "postBattle" "trigger": "postBattle"
}, },
{ {
"name": "enfeeble", "name": "hive_link",
"value": 5, "value": 5,
"all": true, "all": true
"trigger": "preBattle"
} }
] ]
}, },
@ -336,25 +332,24 @@
"skills": [ "skills": [
{ {
"name": "cleanse", "name": "cleanse",
"value": 13, "value": 12,
"all": true, "all": true,
"trigger": "postBattle" "trigger": "postBattle"
}, },
{ {
"name": "enfeeble", "name": "hive_link",
"value": 7, "value": 7,
"all": true, "all": true
"trigger": "preBattle"
}, },
{ {
"name": "counter", "name": "counter",
"value": 10, "value": 8,
"trigger": "on_defend" "trigger": "on_defend"
} }
] ]
} }
], ],
"flavorText": "He built an empire by breaking every enemy from within.", "flavorText": "It is not I whom has lost their mind, it is YOU!",
"artKey": "imp_cmd_4" "artKey": "imp_cmd_4"
}, },
{ {
@ -2131,7 +2126,7 @@
] ]
} }
], ],
"flavorText": "The Khan takes what he wants. Everything else burns.", "flavorText": "You don't think I see your weakness commander?",
"artKey": "raider_cmd_1" "artKey": "raider_cmd_1"
}, },
{ {
@ -2227,7 +2222,7 @@
] ]
} }
], ],
"flavorText": "Strip them of their edge. Then make them feel it.", "flavorText": "Smash it! Smash it all!!!",
"artKey": "raider_cmd_2" "artKey": "raider_cmd_2"
}, },
{ {
@ -2244,10 +2239,10 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "enfeeble", "name": "wound",
"value": 1, "value": 2,
"all": true, "all": true,
"trigger": "preBattle" "trigger": "on_attack"
} }
] ]
}, },
@ -2258,10 +2253,10 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "enfeeble", "name": "wound",
"value": 5, "value": 4,
"all": true, "all": true,
"trigger": "preBattle" "trigger": "on_attack"
} }
] ]
}, },
@ -2279,7 +2274,8 @@
}, },
{ {
"name": "wound", "name": "wound",
"value": 6, "value": 5,
"all": true,
"trigger": "on_attack" "trigger": "on_attack"
} }
] ]
@ -2298,7 +2294,8 @@
}, },
{ {
"name": "wound", "name": "wound",
"value": 9, "value": 7,
"all": true,
"trigger": "on_attack" "trigger": "on_attack"
} }
] ]
@ -2317,7 +2314,8 @@
}, },
{ {
"name": "wound", "name": "wound",
"value": 13, "value": 9,
"all": true,
"trigger": "on_attack" "trigger": "on_attack"
} }
] ]
@ -4070,7 +4068,7 @@
] ]
} }
], ],
"flavorText": "She drinks deeply, and the battlefield withers.", "flavorText": "Drain their blood and restore my people.",
"artKey": "bt_cmd_1" "artKey": "bt_cmd_1"
}, },
{ {
@ -4164,7 +4162,7 @@
] ]
} }
], ],
"flavorText": "It does not rule with fear. It rules with hunger.", "flavorText": "I care little for your pathetic crusade.",
"artKey": "bt_cmd_2" "artKey": "bt_cmd_2"
}, },
{ {
@ -4263,7 +4261,7 @@
] ]
} }
], ],
"flavorText": "Every wound is a gift. Every scar, a sermon.", "flavorText": "Hurt them.. Then finish them off!",
"artKey": "bt_cmd_3" "artKey": "bt_cmd_3"
}, },
{ {
@ -6146,7 +6144,7 @@
] ]
} }
], ],
"flavorText": "The Alpha does not lead. It commands through shared fury.", "flavorText": "You shall not see the Alpha or his army coming!",
"artKey": "xeno_cmd_2" "artKey": "xeno_cmd_2"
}, },
{ {
@ -6261,7 +6259,7 @@
] ]
} }
], ],
"flavorText": "One mind. A billion claws. It has already seen what you will do next.", "flavorText": "One mind -- A billion spawn. It has already seen what you will do next.",
"artKey": "xeno_cmd_3" "artKey": "xeno_cmd_3"
}, },
{ {
@ -7903,6 +7901,12 @@
"name": "cleanse", "name": "cleanse",
"value": 3, "value": 3,
"trigger": "postBattle" "trigger": "postBattle"
},
{
"name": "rally",
"value": 6,
"all": true,
"trigger": "preBattle"
} }
] ]
}, },
@ -7916,6 +7920,12 @@
"name": "cleanse", "name": "cleanse",
"value": 5, "value": 5,
"trigger": "postBattle" "trigger": "postBattle"
},
{
"name": "rally",
"value": 8,
"all": true,
"trigger": "preBattle"
} }
] ]
}, },
@ -7929,11 +7939,17 @@
"name": "cleanse", "name": "cleanse",
"value": 7, "value": 7,
"trigger": "postBattle" "trigger": "postBattle"
},
{
"name": "rally",
"value": 10,
"all": true,
"trigger": "preBattle"
} }
] ]
} }
], ],
"flavorText": "All impurity shall be scoured from this sector.", "flavorText": "10 IF infected = 0 END, 20 infected = 1, 30 GOTO 10",
"artKey": "right_cmd_1" "artKey": "right_cmd_1"
}, },
{ {
@ -7950,8 +7966,9 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "overcharge", "name": "fortify",
"value": 2, "value": 2,
"all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
] ]
@ -7963,8 +7980,9 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "overcharge", "name": "fortify",
"value": 3, "value": 3,
"all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
] ]
@ -7976,8 +7994,15 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "overcharge", "name": "fortify",
"value": 5, "value": 5,
"all": true,
"trigger": "preBattle"
},
{
"name": "heal",
"value": 2,
"all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
] ]
@ -7989,8 +8014,15 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "overcharge", "name": "fortify",
"value": 7, "value": 7,
"all": true,
"trigger": "preBattle"
},
{
"name": "heal",
"value": 4,
"all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
] ]
@ -8002,14 +8034,21 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "overcharge", "name": "fortify",
"value": 10, "value": 10,
"all": true,
"trigger": "preBattle"
},
{
"name": "heal",
"value": 5,
"all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
] ]
} }
], ],
"flavorText": "Pain is the price of devotion. The faithful pay gladly.", "flavorText": "while (armor < value) do, armor := armour + 1",
"artKey": "right_cmd_2" "artKey": "right_cmd_2"
}, },
{ {
@ -8026,9 +8065,8 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "fortify", "name": "overcharge",
"value": 2, "value": 2,
"all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
] ]
@ -8040,9 +8078,8 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "fortify", "name": "overcharge",
"value": 3, "value": 3,
"all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
] ]
@ -8054,7 +8091,12 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "fortify", "name": "overcharge",
"value": 4,
"trigger": "preBattle"
},
{
"name": "smite",
"value": 5, "value": 5,
"all": true, "all": true,
"trigger": "preBattle" "trigger": "preBattle"
@ -8068,8 +8110,13 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "fortify", "name": "overcharge",
"value": 7, "value": 6,
"trigger": "preBattle"
},
{
"name": "smite",
"value": 8,
"all": true, "all": true,
"trigger": "preBattle" "trigger": "preBattle"
} }
@ -8082,7 +8129,12 @@
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ {
"name": "fortify", "name": "overcharge",
"value": 8,
"trigger": "preBattle"
},
{
"name": "smite",
"value": 10, "value": 10,
"all": true, "all": true,
"trigger": "preBattle" "trigger": "preBattle"
@ -8090,7 +8142,7 @@
] ]
} }
], ],
"flavorText": "The future is calculated. Your defeat is certain.", "flavorText": "if holyVirus === NULL { pushHolyVirus(); }",
"artKey": "right_cmd_3" "artKey": "right_cmd_3"
}, },
{ {

View File

@ -206,13 +206,14 @@
{ {
"name": "hive_link", "name": "hive_link",
"description": "On death, all allied xeno cards gain +value ATK permanently.", "description": "On death, all allied xeno cards gain +value ATK permanently.",
"allDescription": "When any allied card is destroyed, all allied cards gain +value ATK permanently.",
"trigger": "on_death", "trigger": "on_death",
"category": "offense" "category": "offense"
}, },
{ {
"name": "cleanse", "name": "cleanse",
"description": "Before battle: cleanse all negative effects (venom, smite, enfeeble, jam, wound) from self.", "description": "After battle: cleanse value damage-over-time effects (venom, smite, wound) from self.",
"allDescription": "Before battle: cleanse all negative effects from ALL allied cards.", "allDescription": "After battle: cleanse value damage-over-time effects from ALL allied cards.",
"trigger": "preBattle", "trigger": "preBattle",
"category": "support", "category": "support",
"supportsAll": true "supportsAll": true

View File

@ -591,6 +591,7 @@ export class CombatEngine {
const strikeFires = []; const strikeFires = [];
const woundFires = []; const woundFires = [];
const venomFires = []; const venomFires = [];
const smiteFires = [];
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) {
@ -734,6 +735,13 @@ export class CombatEngine {
venomFires.push({ skill: 'venom', source: card, target: ctx.venomTarget, stacks: ctx.venomStacks }); venomFires.push({ skill: 'venom', source: card, target: ctx.venomTarget, stacks: ctx.venomStacks });
this._log(`${card.name} venom: applied ${ctx.venomStacks} stacks to ${ctx.venomTarget.name}`); this._log(`${card.name} venom: applied ${ctx.venomStacks} stacks to ${ctx.venomTarget.name}`);
} }
if (s.name === 'smite' && ctx.smiteAllTargets) {
smiteFires.push({ skill: 'smite', source: card, isAll: true, targets: ctx.smiteAllTargets });
this._log(`${card.name} smite all: applied stacks to ${ctx.smiteAllTargets.length} enemies`);
} else if (s.name === 'smite' && ctx.smiteTarget) {
smiteFires.push({ skill: 'smite', source: card, target: ctx.smiteTarget, stacks: ctx.smiteStacks });
this._log(`${card.name} smite: applied ${ctx.smiteStacks} stacks to ${ctx.smiteTarget.name}`);
}
if (s.name === 'strike' && ctx.strikeAllTargets) { if (s.name === 'strike' && ctx.strikeAllTargets) {
const isPlayerCard = this.playerLanes.includes(card) || card === this.playerCommander; const isPlayerCard = this.playerLanes.includes(card) || card === this.playerCommander;
for (const t of ctx.strikeAllTargets) { for (const t of ctx.strikeAllTargets) {
@ -763,7 +771,7 @@ export class CombatEngine {
} }
} }
} }
return { buffs, siegeFires, protectFires, enfeebeFires, jamFires, weakenFires, drainFires, healFires, overchargeFires, fortifyFires, strikeFires, woundFires, venomFires }; return { buffs, siegeFires, protectFires, enfeebeFires, jamFires, weakenFires, drainFires, healFires, overchargeFires, fortifyFires, strikeFires, woundFires, venomFires, smiteFires };
} }
// Emit the 8-step pre-battle sequence and process preBattle skills. // Emit the 8-step pre-battle sequence and process preBattle skills.
@ -784,8 +792,8 @@ export class CombatEngine {
const otherAllies = [otherCmd, ...otherLanes]; const otherAllies = [otherCmd, ...otherLanes];
// Steps 1–2: commander defensive buffs (placeholder — no defensive skills yet) // Steps 1–2: commander defensive buffs (placeholder — no defensive skills yet)
this.events.push({ type: 'preBattle', phase: 'defensive', target: 'commander', side: firstSide, card: firstCmd, buffs: [], siegeFires: [], protectFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [] }); this.events.push({ type: 'preBattle', phase: 'defensive', target: 'commander', side: firstSide, card: firstCmd, buffs: [], siegeFires: [], protectFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [], smiteFires: [] });
this.events.push({ type: 'preBattle', phase: 'defensive', target: 'commander', side: otherSide, card: otherCmd, buffs: [], siegeFires: [], protectFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [] }); this.events.push({ type: 'preBattle', phase: 'defensive', target: 'commander', side: otherSide, card: otherCmd, buffs: [], siegeFires: [], protectFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [], smiteFires: [] });
// Steps 3–4: commander offensive buffs (pass actual enemy lanes so all-targeting skills work) // Steps 3–4: commander offensive buffs (pass actual enemy lanes so all-targeting skills work)
const firstCmdFires = this._collectPreBattleFires([firstCmd], firstAllies, otherAllies, otherCmd, otherLanes); const firstCmdFires = this._collectPreBattleFires([firstCmd], firstAllies, otherAllies, otherCmd, otherLanes);
@ -794,8 +802,8 @@ export class CombatEngine {
this.events.push({ type: 'preBattle', phase: 'offensive', target: 'commander', side: otherSide, card: otherCmd, ...otherCmdFires }); this.events.push({ type: 'preBattle', phase: 'offensive', target: 'commander', side: otherSide, card: otherCmd, ...otherCmdFires });
// Steps 5–6: lane defensive buffs (placeholder) // Steps 5–6: lane defensive buffs (placeholder)
this.events.push({ type: 'preBattle', phase: 'defensive', target: 'lanes', side: firstSide, cards: firstLanes, buffs: [], siegeFires: [], protectFires: [], enfeebeFires: [], jamFires: [], healFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [] }); this.events.push({ type: 'preBattle', phase: 'defensive', target: 'lanes', side: firstSide, cards: firstLanes, buffs: [], siegeFires: [], protectFires: [], enfeebeFires: [], jamFires: [], healFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [], smiteFires: [] });
this.events.push({ type: 'preBattle', phase: 'defensive', target: 'lanes', side: otherSide, cards: otherLanes, buffs: [], siegeFires: [], protectFires: [], enfeebeFires: [], jamFires: [], healFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [] }); this.events.push({ type: 'preBattle', phase: 'defensive', target: 'lanes', side: otherSide, cards: otherLanes, buffs: [], siegeFires: [], protectFires: [], enfeebeFires: [], jamFires: [], healFires: [], overchargeFires: [], fortifyFires: [], woundFires: [], venomFires: [], smiteFires: [] });
// Steps 7–8: lane offensive buffs + all skill fires // Steps 7–8: lane offensive buffs + all skill fires
const firstLaneFires = this._collectPreBattleFires(firstLanes, firstAllies, otherAllies, otherCmd, otherLanes); const firstLaneFires = this._collectPreBattleFires(firstLanes, firstAllies, otherAllies, otherCmd, otherLanes);
@ -1167,6 +1175,7 @@ export class CombatEngine {
const cleanseFires = []; const cleanseFires = [];
const liveCards = allSideCards.filter(c => c && c.currentHP > 0); const liveCards = allSideCards.filter(c => c && c.currentHP > 0);
for (const card of liveCards) { for (const card of liveCards) {
if ((card.currentDelay || 0) > 0) continue;
for (const s of card.skills) { for (const s of card.skills) {
if (s.name === 'cleanse' && s.trigger === 'postBattle') { if (s.name === 'cleanse' && s.trigger === 'postBattle') {
const ctx = { rng: this.rng }; const ctx = { rng: this.rng };

View File

@ -579,8 +579,9 @@ export class SkillProcessor {
const allTargets = []; const allTargets = [];
for (const t of targets) { for (const t of targets) {
if (t.smiteStacks < skill.value) { if (t.smiteStacks < skill.value) {
const prevStacks = t.smiteStacks;
t.smiteStacks = skill.value; t.smiteStacks = skill.value;
allTargets.push({ target: t, stacks: skill.value }); allTargets.push({ target: t, stacks: skill.value, prevStacks });
} }
} }
if (context && allTargets.length > 0) context.smiteAllTargets = allTargets; if (context && allTargets.length > 0) context.smiteAllTargets = allTargets;

View File

@ -154,10 +154,10 @@ export class CardObject extends Phaser.GameObjects.Container {
this.add(this.burrowBadge); this.add(this.burrowBadge);
this._updateBurrowBadge(); this._updateBurrowBadge();
// Wound stack indicator (below burrow badge, red) // Wound stack indicator (upper-left of image area, below level badge, red)
this.woundBadge = this.scene.add.text( this.woundBadge = this.scene.add.text(
w / 2 - Math.round(4 * scale), -w / 2 + Math.round(4 * scale),
-h / 2 + bannerH + Math.round(45 * scale), -h / 2 + bannerH + Math.round(15 * scale),
'', '',
{ {
fontSize: fs(7), color: '#ff4444', fontStyle: 'bold', fontSize: fs(7), color: '#ff4444', fontStyle: 'bold',
@ -165,7 +165,7 @@ export class CardObject extends Phaser.GameObjects.Container {
padding: { x: Math.round(2 * scale), y: Math.round(1 * scale) }, padding: { x: Math.round(2 * scale), y: Math.round(1 * scale) },
fontFamily: 'Audiowide' fontFamily: 'Audiowide'
} }
).setOrigin(1, 0); ).setOrigin(0, 0);
this.woundBadge.setVisible(false); this.woundBadge.setVisible(false);
this.add(this.woundBadge); this.add(this.woundBadge);
this._updateWoundBadge(); this._updateWoundBadge();

View File

@ -844,6 +844,7 @@ export class BattleScene extends Phaser.Scene {
this._restoreFortifyForDisplay(preBattleEvents); this._restoreFortifyForDisplay(preBattleEvents);
this._restorePreBattleWoundFires(preBattleEvents); this._restorePreBattleWoundFires(preBattleEvents);
this._restorePreBattleVenomFires(preBattleEvents); this._restorePreBattleVenomFires(preBattleEvents);
this._restorePreBattleSmiteFires(preBattleEvents);
this._restoreSiegeFiresForDisplay(preBattleEvents); this._restoreSiegeFiresForDisplay(preBattleEvents);
// Render the field with all newly deployed cards but pre-combat stats // Render the field with all newly deployed cards but pre-combat stats
this._renderState(); this._renderState();
@ -857,6 +858,7 @@ export class BattleScene extends Phaser.Scene {
this._reapplyFortify(preBattleEvents); this._reapplyFortify(preBattleEvents);
this._reapplyPreBattleWoundFires(preBattleEvents); this._reapplyPreBattleWoundFires(preBattleEvents);
this._reapplyPreBattleVenomFires(preBattleEvents); this._reapplyPreBattleVenomFires(preBattleEvents);
this._reapplyPreBattleSmiteFires(preBattleEvents);
this._reapplySiegeFires(preBattleEvents); this._reapplySiegeFires(preBattleEvents);
const newPlayerCard = chosenCard const newPlayerCard = chosenCard
@ -1074,7 +1076,7 @@ export class BattleScene extends Phaser.Scene {
targets: knife, targets: knife,
x: targetObj.x, x: targetObj.x,
y: targetObj.y, y: targetObj.y,
duration: 2000, duration: 500,
ease: 'Quad.In', ease: 'Quad.In',
onComplete: () => { onComplete: () => {
if (knife.scene) knife.destroy(); if (knife.scene) knife.destroy();
@ -1143,7 +1145,7 @@ export class BattleScene extends Phaser.Scene {
scaleX: { from: effectSprite.scaleX * 0.8, to: effectSprite.scaleX * 1.5 }, scaleX: { from: effectSprite.scaleX * 0.8, to: effectSprite.scaleX * 1.5 },
scaleY: { from: effectSprite.scaleY * 0.8, to: effectSprite.scaleY * 1.5 }, scaleY: { from: effectSprite.scaleY * 0.8, to: effectSprite.scaleY * 1.5 },
alpha: { from: 0.9, to: 0.2 }, alpha: { from: 0.9, to: 0.2 },
duration: 500, duration: 250,
yoyo: true, yoyo: true,
repeat: 1, repeat: 1,
onComplete: () => { if (effectSprite.scene) effectSprite.destroy(); } onComplete: () => { if (effectSprite.scene) effectSprite.destroy(); }
@ -2770,21 +2772,25 @@ export class BattleScene extends Phaser.Scene {
const hasStrike = event.strikeFires?.length > 0; const hasStrike = event.strikeFires?.length > 0;
const hasWound = event.woundFires?.length > 0; const hasWound = event.woundFires?.length > 0;
const hasVenom = event.venomFires?.length > 0; const hasVenom = event.venomFires?.length > 0;
const hasSmite = event.smiteFires?.length > 0;
if (hasBuffs || hasSiege || hasProtect || hasEnfeeble || hasJam || hasWeaken || hasDrain || hasHeal || hasOvercharge || hasFortify || hasStrike || hasWound || hasVenom) { if (hasBuffs || hasSiege || hasProtect || hasEnfeeble || hasJam || hasWeaken || hasDrain || hasHeal || hasOvercharge || hasFortify || hasStrike || hasWound || hasVenom || hasSmite) {
this._processPreBattleVenomFires(event.venomFires || [], () => { this._processPreBattleSmiteFires(event.smiteFires || [], () => {
this._processPreBattleWoundFires(event.woundFires || [], () => { this._processPreBattleVenomFires(event.venomFires || [], () => {
this._processDrainFires(event.drainFires || [], () => { this._processPreBattleWoundFires(event.woundFires || [], () => {
this._processOverchargeFires(event.overchargeFires || [], () => { this._processDrainFires(event.drainFires || [], () => {
this._processBuffAnimations(event.buffs || [], () => { this._processOverchargeFires(event.overchargeFires || [], () => {
this._processFortifyFires(event.fortifyFires || [], () => { this._processBuffAnimations(event.buffs || [], () => {
this._processSiegeFires(event.siegeFires || [], () => { this._processFortifyFires(event.fortifyFires || [], () => {
this._processPreBattleStrikeFires(event.strikeFires || [], () => { 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);
});
});
}); });
}); });
}); });
@ -2794,14 +2800,52 @@ export class BattleScene extends Phaser.Scene {
}); });
}); });
}); });
}); });
});
}); });
} else { } else {
onComplete(); onComplete();
} }
} }
_processPreBattleSmiteFires(fires, onComplete) {
if (!fires || fires.length === 0) { onComplete(); return; }
const next = (idx) => {
if (idx >= fires.length) { onComplete(); return; }
const fire = fires[idx];
const adapted = { ...fire, attacker: fire.source };
if (fire.isAll) {
this._animateSmiteApplyAll(adapted, () => next(idx + 1));
} else {
this._animateSmiteApply(adapted, () => next(idx + 1));
}
};
next(0);
}
_restorePreBattleSmiteFires(preBattleEvents) {
for (const event of preBattleEvents) {
for (const fire of event.smiteFires || []) {
if (fire.isAll) {
for (const t of fire.targets) t.target.smiteStacks = t.prevStacks;
} else if (fire.target) {
fire.target.smiteStacks = fire.prevStacks ?? 0;
}
}
}
}
_reapplyPreBattleSmiteFires(preBattleEvents) {
for (const event of preBattleEvents) {
for (const fire of event.smiteFires || []) {
if (fire.isAll) {
for (const t of fire.targets) t.target.smiteStacks = t.stacks;
} else if (fire.target) {
fire.target.smiteStacks = fire.stacks;
}
}
}
}
_processPreBattleVenomFires(fires, onComplete) { _processPreBattleVenomFires(fires, onComplete) {
if (!fires || fires.length === 0) { onComplete(); return; } if (!fires || fires.length === 0) { onComplete(); return; }
const next = (idx) => { const next = (idx) => {
@ -3912,7 +3956,7 @@ export class BattleScene extends Phaser.Scene {
targets: enfeebleSprite, targets: enfeebleSprite,
scaleX: BASE_SCALE * 1.25, scaleX: BASE_SCALE * 1.25,
scaleY: BASE_SCALE * 1.25, scaleY: BASE_SCALE * 1.25,
duration: 200, duration: 100,
ease: 'Sine.easeInOut', ease: 'Sine.easeInOut',
yoyo: true, yoyo: true,
repeat: 2, repeat: 2,
@ -3969,7 +4013,7 @@ export class BattleScene extends Phaser.Scene {
this.tweens.add({ this.tweens.add({
targets: enfeebleSprite, targets: enfeebleSprite,
scaleX: BASE_SCALE * 1.25, scaleY: BASE_SCALE * 1.25, scaleX: BASE_SCALE * 1.25, scaleY: BASE_SCALE * 1.25,
duration: 200, ease: 'Sine.easeInOut', yoyo: true, repeat: 2, duration: 100, ease: 'Sine.easeInOut', yoyo: true, repeat: 2,
onComplete: () => { onComplete: () => {
if (!enfeebleSprite.scene) { onComplete(); return; } if (!enfeebleSprite.scene) { onComplete(); return; }
this.tweens.add({ this.tweens.add({
@ -4855,7 +4899,7 @@ export class BattleScene extends Phaser.Scene {
this.tweens.add({ this.tweens.add({
targets: projectile, targets: projectile,
x: targetObj.x, y: targetObj.y, x: targetObj.x, y: targetObj.y,
duration: 2000, duration: 1750,
ease: 'Quad.In', ease: 'Quad.In',
onComplete: () => { onComplete: () => {
if (projectile.scene) projectile.destroy(); if (projectile.scene) projectile.destroy();
@ -4913,7 +4957,7 @@ export class BattleScene extends Phaser.Scene {
targets: effectSprite, targets: effectSprite,
scaleX: { from: 0.8, to: 1.5 }, scaleX: { from: 0.8, to: 1.5 },
scaleY: { from: 0.8, to: 1.5 }, scaleY: { from: 0.8, to: 1.5 },
duration: 250, duration: 150,
yoyo: true, yoyo: true,
repeat: 1, repeat: 1,
onComplete: () => { if (effectSprite.scene) effectSprite.destroy(); } onComplete: () => { if (effectSprite.scene) effectSprite.destroy(); }