bump mission gold rewards and hive_link values; unlock all faction commanders on first campaign clear; enhance Fusion Lab UI
This commit is contained in:
parent
b336f60197
commit
662147cdfb
Binary file not shown.
|
After Width: | Height: | Size: 254 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 302 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 319 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 289 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 318 KiB |
|
|
@ -34,7 +34,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 68,
|
||||
"health": 136,
|
||||
"armor": 5,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 102,
|
||||
"health": 204,
|
||||
"armor": 7,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 152,
|
||||
"health": 304,
|
||||
"armor": 10,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -112,7 +112,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 68,
|
||||
"health": 136,
|
||||
"armor": 9,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 102,
|
||||
"health": 204,
|
||||
"armor": 13,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -140,7 +140,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 152,
|
||||
"health": 304,
|
||||
"armor": 20,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -193,7 +193,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 57,
|
||||
"health": 114,
|
||||
"armor": 3,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -207,7 +207,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 85,
|
||||
"health": 170,
|
||||
"armor": 4,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -221,7 +221,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 127,
|
||||
"health": 254,
|
||||
"armor": 5,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -286,7 +286,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 68,
|
||||
"health": 136,
|
||||
"armor": 7,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -306,7 +306,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 102,
|
||||
"health": 204,
|
||||
"armor": 10,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -326,7 +326,7 @@
|
|||
},
|
||||
{
|
||||
"attack": 0,
|
||||
"health": 152,
|
||||
"health": 304,
|
||||
"armor": 15,
|
||||
"delay": 0,
|
||||
"skills": [
|
||||
|
|
@ -6256,7 +6256,7 @@
|
|||
"skills": [
|
||||
{
|
||||
"name": "hive_link",
|
||||
"value": 2,
|
||||
"value": 3,
|
||||
"trigger": "passive"
|
||||
}
|
||||
]
|
||||
|
|
@ -6269,7 +6269,7 @@
|
|||
"skills": [
|
||||
{
|
||||
"name": "hive_link",
|
||||
"value": 4,
|
||||
"value": 5,
|
||||
"trigger": "passive"
|
||||
}
|
||||
]
|
||||
|
|
@ -6282,7 +6282,7 @@
|
|||
"skills": [
|
||||
{
|
||||
"name": "hive_link",
|
||||
"value": 8,
|
||||
"value": 10,
|
||||
"trigger": "passive"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 150,
|
||||
"gold": 1200,
|
||||
"cards": [
|
||||
"xeno_drone_1"
|
||||
]
|
||||
|
|
@ -408,7 +408,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 200,
|
||||
"gold": 1300,
|
||||
"cards": [
|
||||
"xeno_spitter_1"
|
||||
]
|
||||
|
|
@ -435,7 +435,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 250,
|
||||
"gold": 1400,
|
||||
"cards": [
|
||||
"xeno_beetle_1"
|
||||
]
|
||||
|
|
@ -463,7 +463,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 300,
|
||||
"gold": 1500,
|
||||
"cards": [
|
||||
"xeno_worker_1"
|
||||
]
|
||||
|
|
@ -491,7 +491,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 350,
|
||||
"gold": 1600,
|
||||
"cards": [
|
||||
"xeno_guard_1"
|
||||
]
|
||||
|
|
@ -519,7 +519,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 400,
|
||||
"gold": 1700,
|
||||
"cards": [
|
||||
"xeno_mantis_1"
|
||||
]
|
||||
|
|
@ -547,7 +547,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 450,
|
||||
"gold": 1800,
|
||||
"cards": [
|
||||
"xeno_horror_1"
|
||||
]
|
||||
|
|
@ -575,7 +575,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 500,
|
||||
"gold": 1900,
|
||||
"cards": [
|
||||
"xeno_hiveguard_1"
|
||||
]
|
||||
|
|
@ -602,7 +602,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 100,
|
||||
"gold": 2000,
|
||||
"cards": [
|
||||
"right_acolyte_1"
|
||||
]
|
||||
|
|
@ -629,7 +629,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 150,
|
||||
"gold": 2100,
|
||||
"cards": [
|
||||
"right_pilgrim_1"
|
||||
]
|
||||
|
|
@ -656,7 +656,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 200,
|
||||
"gold": 2200,
|
||||
"cards": [
|
||||
"right_sentinel_1"
|
||||
]
|
||||
|
|
@ -683,7 +683,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 250,
|
||||
"gold": 2300,
|
||||
"cards": [
|
||||
"right_hacker_1"
|
||||
]
|
||||
|
|
@ -710,7 +710,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 300,
|
||||
"gold": 2400,
|
||||
"cards": [
|
||||
"right_zealot_1"
|
||||
]
|
||||
|
|
@ -737,7 +737,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 350,
|
||||
"gold": 2500,
|
||||
"cards": [
|
||||
"right_templar_1"
|
||||
]
|
||||
|
|
@ -762,7 +762,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 400,
|
||||
"gold": 2600,
|
||||
"cards": [
|
||||
"right_purifier_1"
|
||||
]
|
||||
|
|
@ -789,7 +789,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 450,
|
||||
"gold": 2700,
|
||||
"cards": [
|
||||
"right_prophet_1"
|
||||
]
|
||||
|
|
@ -816,7 +816,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 200,
|
||||
"gold": 2800,
|
||||
"cards": [
|
||||
"imp_trooper_1"
|
||||
]
|
||||
|
|
@ -843,7 +843,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 250,
|
||||
"gold": 2900,
|
||||
"cards": [
|
||||
"imp_shieldwall_1"
|
||||
]
|
||||
|
|
@ -870,7 +870,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 300,
|
||||
"gold": 3000,
|
||||
"cards": [
|
||||
"imp_gunner_1"
|
||||
]
|
||||
|
|
@ -898,7 +898,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 350,
|
||||
"gold": 3100,
|
||||
"cards": [
|
||||
"imp_sniper_1"
|
||||
]
|
||||
|
|
@ -926,7 +926,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 400,
|
||||
"gold": 3200,
|
||||
"cards": [
|
||||
"imp_mortar_1"
|
||||
]
|
||||
|
|
@ -953,7 +953,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 450,
|
||||
"gold": 3300,
|
||||
"cards": [
|
||||
"imp_praetorian_1"
|
||||
]
|
||||
|
|
@ -981,7 +981,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 500,
|
||||
"gold": 3400,
|
||||
"cards": [
|
||||
"imp_sentinel_1"
|
||||
]
|
||||
|
|
@ -1008,7 +1008,7 @@
|
|||
]
|
||||
},
|
||||
"rewards": {
|
||||
"gold": 600,
|
||||
"gold": 3500,
|
||||
"cards": [
|
||||
"imp_dreadnought_1"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4129,15 +4129,21 @@ export class BattleScene extends Phaser.Scene {
|
|||
rewards.cards.forEach(cardId => SaveManager.addCard(save, cardId));
|
||||
}
|
||||
|
||||
// Check if this is the final mission of a campaign — if so, unlock the enemy commander (once only)
|
||||
let unlockedCommander = null;
|
||||
const campaigns = this.registry.get('campaigns') || [];
|
||||
const campaign = campaigns.find(c => c.missions && c.missions[c.missions.length - 1] === this.missionData.id);
|
||||
if (campaign) {
|
||||
const commanderId = this.missionData.opponent?.commander;
|
||||
if (commanderId && !save.collection[commanderId]) {
|
||||
SaveManager.addCard(save, commanderId);
|
||||
unlockedCommander = commanderId;
|
||||
// Check if this is the final mission of a campaign — if so, unlock all faction commanders (first clear only)
|
||||
let unlockedCommanders = [];
|
||||
if (firstClear) {
|
||||
const campaigns = this.registry.get('campaigns') || [];
|
||||
const campaign = campaigns.find(c => c.missions && c.missions[c.missions.length - 1] === this.missionData.id);
|
||||
if (campaign) {
|
||||
const faction = this.missionData.campaignId.replace('campaign_', '');
|
||||
const cardManager = this.registry.get('cardManager');
|
||||
const factionCommanders = cardManager.getAllCards().filter(c => c.type === 'commander' && c.faction === faction);
|
||||
for (const cmd of factionCommanders) {
|
||||
if (!save.collection[cmd.id]) {
|
||||
SaveManager.addCard(save, cmd.id);
|
||||
unlockedCommanders.push(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4158,12 +4164,10 @@ export class BattleScene extends Phaser.Scene {
|
|||
}).setOrigin(0.5);
|
||||
}
|
||||
|
||||
if (unlockedCommander) {
|
||||
const cardManager = this.registry.get('cardManager');
|
||||
const cmdCard = cardManager.getCard(unlockedCommander);
|
||||
const cmdName = cmdCard ? cmdCard.name : unlockedCommander;
|
||||
this.add.text(width / 2, height / 2 + 110, `Commander unlocked: ${cmdName}!`, {
|
||||
fontSize: '22px', color: '#ffdd44', fontFamily: 'Audiowide'
|
||||
if (unlockedCommanders.length > 0) {
|
||||
const names = unlockedCommanders.map(c => c.name).join(', ');
|
||||
this.add.text(width / 2, height / 2 + 110, `Commanders unlocked: ${names}!`, {
|
||||
fontSize: '20px', color: '#ffdd44', fontFamily: 'Audiowide'
|
||||
}).setOrigin(0.5);
|
||||
}
|
||||
} else if (!won && this.missionData) {
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ const RARITY_COLORS = {
|
|||
|
||||
// Layout constants
|
||||
const STACKS_LEFT = 20;
|
||||
const STACKS_TOP = 100;
|
||||
const STACKS_TOP = 120;
|
||||
const STACKS_W = 700;
|
||||
const STACKS_H = 710;
|
||||
const STACKS_H = 690;
|
||||
const CARD_W = 185;
|
||||
const CARD_H = 255;
|
||||
const CELL_W = 205;
|
||||
|
|
@ -104,10 +104,81 @@ export class FusionScene extends Phaser.Scene {
|
|||
// ── Header ─────────────────────────────────────────────────────────────────
|
||||
|
||||
_buildHeader() {
|
||||
this.add.text(360, 28, 'FUSION LAB', {
|
||||
fontSize: '36px', color: '#d4af37', fontStyle: 'bold', fontFamily: 'RaiderCrusader'
|
||||
const cx = 360;
|
||||
const titleY = 48;
|
||||
|
||||
// ── Layered pulsing plasma glow behind the title ──────────────────────
|
||||
// Three concentric layers: wide+faint → narrow+bright, each pulsing at a
|
||||
// different rate to create a breathing, living energy effect.
|
||||
const glowLayers = [
|
||||
{ w: 580, h: 84, color: 0x001500, alphaMin: 0.08, alphaMax: 0.18, dur: 2200 },
|
||||
{ w: 400, h: 60, color: 0x004400, alphaMin: 0.12, alphaMax: 0.26, dur: 1700, delay: 350 },
|
||||
{ w: 240, h: 38, color: 0x00bb44, alphaMin: 0.16, alphaMax: 0.42, dur: 1200, delay: 700 },
|
||||
];
|
||||
for (const l of glowLayers) {
|
||||
const g = this.add.graphics();
|
||||
g.fillStyle(l.color, 1);
|
||||
g.fillRect(cx - l.w / 2, titleY - l.h / 2, l.w, l.h);
|
||||
g.setAlpha(l.alphaMin);
|
||||
this.tweens.add({
|
||||
targets: g,
|
||||
alpha: { from: l.alphaMin, to: l.alphaMax },
|
||||
duration: l.dur,
|
||||
delay: l.delay || 0,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
ease: 'Sine.InOut'
|
||||
});
|
||||
}
|
||||
|
||||
// ── Horizontal accent lines (top & bottom of glow) ────────────────────
|
||||
for (const yOff of [-34, 34]) {
|
||||
const line = this.add.graphics();
|
||||
line.fillStyle(0x00cc44, 1);
|
||||
line.fillRect(cx - 240, titleY + yOff, 480, 1);
|
||||
line.setAlpha(0.35);
|
||||
this.tweens.add({
|
||||
targets: line,
|
||||
alpha: { from: 0.2, to: 0.6 },
|
||||
duration: 2400,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
ease: 'Sine.InOut'
|
||||
});
|
||||
}
|
||||
|
||||
// ── Periodic scan sweep across the glow ──────────────────────────────
|
||||
// A thin vertical bar of light drifts left→right every few seconds,
|
||||
// like an energy pulse charging through the machine.
|
||||
const sweep = this.add.graphics();
|
||||
sweep.fillStyle(0x88ffb0, 1);
|
||||
sweep.fillRect(0, titleY - 36, 3, 72);
|
||||
sweep.setAlpha(0);
|
||||
|
||||
const doSweep = () => {
|
||||
if (!sweep.scene) return;
|
||||
sweep.x = cx - 260;
|
||||
this.tweens.add({
|
||||
targets: sweep,
|
||||
x: cx + 260,
|
||||
alpha: { from: 0.75, to: 0 },
|
||||
duration: 650,
|
||||
ease: 'Quad.In',
|
||||
onComplete: () => { this.time.delayedCall(4500, doSweep); }
|
||||
});
|
||||
};
|
||||
this.time.delayedCall(1200, doSweep);
|
||||
|
||||
// ── Title text with a soft cyan postFX glow ───────────────────────────
|
||||
const titleText = this.add.text(cx, titleY, 'FUSION LAB', {
|
||||
fontSize: '36px', color: '#d4af37', fontStyle: 'bold', fontFamily: 'RaiderCrusader',
|
||||
stroke: '#001a00', strokeThickness: 4
|
||||
}).setOrigin(0.5);
|
||||
this.add.text(360, 58, 'Combine 3 copies of a card to forge a stronger one', {
|
||||
if (titleText.postFX) {
|
||||
titleText.postFX.addGlow(0x00ff55, 5, 0, false, 0.14, 14);
|
||||
}
|
||||
|
||||
this.add.text(cx, 82, 'Combine 3 copies of a card to forge a stronger one', {
|
||||
fontSize: '16px', color: '#888888', fontFamily: 'Audiowide'
|
||||
}).setOrigin(0.5);
|
||||
}
|
||||
|
|
@ -257,16 +328,16 @@ export class FusionScene extends Phaser.Scene {
|
|||
});
|
||||
|
||||
// Info text (visible when a stack is selected)
|
||||
this._fuseInfoText = this.add.text(1060, 855, '', {
|
||||
this._fuseInfoText = this.add.text(1060, 900, '', {
|
||||
fontSize: '20px', color: '#ffffff', fontFamily: 'Audiowide'
|
||||
}).setOrigin(0.5).setVisible(false);
|
||||
|
||||
// Fuse button
|
||||
this._fuseBtnBg = this.add.rectangle(1060, 920, 260, 65, 0x553300)
|
||||
this._fuseBtnBg = this.add.rectangle(1060, 970, 260, 65, 0x553300)
|
||||
.setStrokeStyle(3, 0xffaa00)
|
||||
.setInteractive({ useHandCursor: true })
|
||||
.setVisible(false);
|
||||
this._fuseBtnText = this.add.text(1060, 920, 'FUSE', {
|
||||
this._fuseBtnText = this.add.text(1060, 970, 'FUSE', {
|
||||
fontSize: '26px', color: '#ffd700', fontStyle: 'bold', fontFamily: 'Audiowide'
|
||||
}).setOrigin(0.5).setVisible(false);
|
||||
|
||||
|
|
@ -520,7 +591,7 @@ export class FusionScene extends Phaser.Scene {
|
|||
const col = i % 4;
|
||||
const row = Math.floor(i / 4);
|
||||
const x = startX + col * (pw + gap);
|
||||
const y = PREVIEW_TOP + 80 + row * (ph + 30);
|
||||
const y = PREVIEW_TOP + 130 + row * (ph + 20);
|
||||
|
||||
const instance = this.cardManager.createInstance(card.id, this.save.level || 1);
|
||||
const cardObj = new CardObject(this, x, y, instance, {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ export class StoreScene extends Phaser.Scene {
|
|||
|
||||
preload() {
|
||||
this.load.video('corridors', 'assets/video/corridors.mp4');
|
||||
this.load.image('pack_imperial', 'assets/images/ui/pack_imperial.png');
|
||||
this.load.image('pack_raider', 'assets/images/ui/pack_raider.png');
|
||||
this.load.image('pack_bloodthirsty', 'assets/images/ui/pack_bloodthirsty.png');
|
||||
this.load.image('pack_xeno', 'assets/images/ui/pack_xeno.png');
|
||||
this.load.image('pack_righteous', 'assets/images/ui/pack_righteous.png');
|
||||
}
|
||||
|
||||
create() {
|
||||
|
|
@ -122,32 +127,12 @@ export class StoreScene extends Phaser.Scene {
|
|||
.setStrokeStyle(3, unlocked ? factionColor : 0x333333);
|
||||
elements.push(packBg);
|
||||
|
||||
// Placeholder pack art
|
||||
const artBg = this.add.rectangle(x, y - 100, 220, 180, factionColor, unlocked ? 0.8 : 0.2)
|
||||
.setStrokeStyle(2, unlocked ? 0xffffff : 0x444444, unlocked ? 0.3 : 0.1);
|
||||
elements.push(artBg);
|
||||
|
||||
// Faction icon text on art
|
||||
const artLabel = this.add.text(x, y - 115, FACTION_LABELS[pack.faction] || '?', {
|
||||
fontSize: '22px', color: unlocked ? '#ffffff' : '#444444',
|
||||
fontStyle: 'bold', fontFamily: 'RaiderCrusader'
|
||||
}).setOrigin(0.5);
|
||||
elements.push(artLabel);
|
||||
|
||||
const artSub = this.add.text(x, y - 80, 'BOOSTER', {
|
||||
fontSize: '14px', color: unlocked ? '#aaaaaa' : '#333333', fontFamily: 'Audiowide'
|
||||
}).setOrigin(0.5);
|
||||
elements.push(artSub);
|
||||
|
||||
// Decorative lines on art
|
||||
const artGfx = this.add.graphics();
|
||||
const lineColor = unlocked ? factionColor : 0x333333;
|
||||
const lineAlpha = unlocked ? 0.5 : 0.15;
|
||||
artGfx.lineStyle(1, lineColor, lineAlpha);
|
||||
artGfx.strokeRect(x - 100, y - 180, 200, 160);
|
||||
artGfx.lineStyle(1, lineColor, lineAlpha * 0.5);
|
||||
artGfx.strokeRect(x - 90, y - 170, 180, 140);
|
||||
elements.push(artGfx);
|
||||
// Pack art image
|
||||
const packImageKey = `pack_${pack.faction}`;
|
||||
const packArt = this.add.image(x, y - 100, packImageKey)
|
||||
.setDisplaySize(220, 180)
|
||||
.setAlpha(unlocked ? 1 : 0.25);
|
||||
elements.push(packArt);
|
||||
|
||||
// Pack name
|
||||
const nameText = this.add.text(x, y + 10, pack.name, {
|
||||
|
|
|
|||
Loading…
Reference in New Issue