tyrants-edge/src/scenes/CampaignScene.js

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');
});
}
}