143 lines
5.3 KiB
JavaScript
143 lines
5.3 KiB
JavaScript
import { SaveManager } from '../managers/SaveManager.js';
|
|
|
|
export class CampaignScene extends Phaser.Scene {
|
|
constructor() { super('CampaignScene'); }
|
|
|
|
init(data) {
|
|
this.campaignId = data.campaignId || 'campaign_raider';
|
|
}
|
|
|
|
create() {
|
|
const allMissions = this.registry.get('missions');
|
|
const campaigns = this.registry.get('campaigns');
|
|
const save = this.registry.get('save');
|
|
const { width, height } = this.scale;
|
|
|
|
const campaign = campaigns.find(c => c.id === this.campaignId);
|
|
const missions = allMissions.filter(m => m.campaignId === this.campaignId);
|
|
|
|
this.add.rectangle(width / 2, height / 2, width, height, 0x0d1b2a);
|
|
this.add.text(width / 2, 45, campaign ? campaign.name : 'Campaign', {
|
|
fontSize: '42px', color: '#d4af37', fontFamily: 'RaiderCrusader'
|
|
}).setOrigin(0.5);
|
|
|
|
if (campaign) {
|
|
this.add.text(width / 2, 90, `Level ${campaign.level} — ${campaign.faction.toUpperCase()}`, {
|
|
fontSize: '18px', color: '#888888', fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
}
|
|
|
|
const completed = save.campaignProgress.completedMissions;
|
|
|
|
// Check if campaign is fully complete
|
|
const allDone = missions.length > 0 && missions.every(m => completed.includes(m.id));
|
|
if (allDone && campaign) {
|
|
this._checkCampaignRewards(campaign, save, campaigns);
|
|
}
|
|
|
|
missions.forEach((mission, i) => {
|
|
const isUnlocked = !mission.unlockCondition || completed.includes(mission.unlockCondition);
|
|
const isDone = completed.includes(mission.id);
|
|
const x = 300 + (i % 4) * 375;
|
|
const y = 380 + Math.floor(i / 4) * 260;
|
|
|
|
const color = isDone ? 0x228822 : isUnlocked ? 0x1a3a5c : 0x333333;
|
|
const borderColor = isDone ? 0x44ff44 : isUnlocked ? 0x4488ff : 0x666666;
|
|
|
|
const node = this.add.rectangle(x, y, 300, 220, color)
|
|
.setStrokeStyle(2, borderColor);
|
|
|
|
if (isUnlocked) {
|
|
node.setInteractive({ useHandCursor: true });
|
|
node.on('pointerover', () => node.setFillStyle(isDone ? 0x33aa33 : 0x2a5a8c));
|
|
node.on('pointerout', () => node.setFillStyle(color));
|
|
node.on('pointerdown', () => this._startMission(mission, campaign));
|
|
}
|
|
|
|
this.add.text(x, y - 70, mission.name, {
|
|
fontSize: '20px', color: isUnlocked ? '#ffffff' : '#666666',
|
|
wordWrap: { width: 270 }, align: 'center', fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
|
|
this.add.text(x, y - 35, `Mission ${i + 1}`, {
|
|
fontSize: '16px', color: '#888888', fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
|
|
this.add.text(x, y, isDone ? 'Complete' : isUnlocked ? 'Click to battle' : 'Locked', {
|
|
fontSize: '16px', color: isDone ? '#44ff44' : isUnlocked ? '#aaffaa' : '#666666', fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
|
|
// Rewards
|
|
this.add.text(x, y + 30, `+${mission.rewards.gold} gold`, {
|
|
fontSize: '14px', color: '#ffd700', fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
|
|
if (mission.rewards.cards && mission.rewards.cards.length > 0) {
|
|
this.add.text(x, y + 55, `Card reward available`, {
|
|
fontSize: '14px', color: '#aaffaa', fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
}
|
|
});
|
|
|
|
// Mission lore panel
|
|
this.loreText = this.add.text(width / 2, height - 70, 'Hover over a mission to learn more.', {
|
|
fontSize: '18px', color: '#888888', align: 'center', wordWrap: { width: width - 100 }, fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
|
|
this._makeBackButton();
|
|
}
|
|
|
|
_startMission(mission, campaign) {
|
|
const save = this.registry.get('save');
|
|
if (!save.decks || save.decks.length === 0) {
|
|
this.add.text(960, 940, 'No deck! Create a deck in Deck Builder first.', {
|
|
fontSize: '22px', color: '#ff4444', fontFamily: 'Audiowide'
|
|
}).setOrigin(0.5);
|
|
return;
|
|
}
|
|
this.sound.play('sfx_menu_select', { volume: 0.7 });
|
|
this.scene.start('BattleScene', {
|
|
mission,
|
|
deck: save.decks[0],
|
|
playerLevel: save.level || 1,
|
|
enemyLevel: save.level || 1,
|
|
campaignId: this.campaignId
|
|
});
|
|
}
|
|
|
|
_checkCampaignRewards(campaign, save, allCampaigns) {
|
|
// Award starter reward cards if not already awarded
|
|
const rewardKey = `campaignReward_${campaign.id}`;
|
|
if (campaign.starterReward?.cards?.length > 0 && !save[rewardKey]) {
|
|
for (const cardId of campaign.starterReward.cards) {
|
|
save.collection[cardId] = (save.collection[cardId] || 0) + 1;
|
|
}
|
|
save[rewardKey] = true;
|
|
|
|
// Level up if completing this campaign grants a new level
|
|
if (campaign.level >= save.level && save.level < 5) {
|
|
save.level = Math.min(5, campaign.level + 1);
|
|
}
|
|
|
|
// Unlock next campaign
|
|
const nextCampaign = allCampaigns.find(c => c.unlockCondition === campaign.id);
|
|
if (nextCampaign && !save.unlockedCampaigns.includes(nextCampaign.id)) {
|
|
save.unlockedCampaigns.push(nextCampaign.id);
|
|
}
|
|
|
|
SaveManager.save(save);
|
|
}
|
|
}
|
|
|
|
_makeBackButton() {
|
|
const bg = this.add.rectangle(80, 45, 160, 50, 0x333333)
|
|
.setInteractive({ useHandCursor: true })
|
|
.setStrokeStyle(1, 0x888888);
|
|
this.add.text(80, 45, 'Back', { fontSize: '18px', color: '#ffffff', fontFamily: 'Audiowide' }).setOrigin(0.5);
|
|
bg.on('pointerdown', () => {
|
|
this.sound.play('sfx_menu_select', { volume: 0.7 });
|
|
this.scene.start('CampaignSelectScene');
|
|
});
|
|
}
|
|
}
|