import { _decorator, sys, resources, JsonAsset } from 'cc'; import { BundleLoader } from '../Core/BundleLoader'; import { LevelConfigManager } from './LevelConfigManager'; import EventBus, { GameEvents } from '../Core/EventBus'; const { ccclass, property } = _decorator; /** * 武器配置数据接口 */ interface WeaponConfig { id: string; name: string; description: string; rarity: string; unlockLevel: number; baseDamage: number; baseSpeed: number; upgradeCosts: number[]; maxLevel: number; } /** * 玩家数据结构 */ export interface PlayerData { // 基本信息 playerId: string; playerName: string; createTime: number; lastPlayTime: number; totalPlayTime: number; // 货币系统 money: number; // 局外钞票 diamonds: number; // 钻石 // 墙体等级系统 wallLevel: number; // 墙体等级 // 关卡进度 currentLevel: number; maxUnlockedLevel: number; levelProgress: { [levelId: number]: LevelProgress }; // 道具和装备 inventory: InventoryData; // 统计数据 statistics: GameStatistics; // 设置 settings: PlayerSettings; } /** * 关卡进度数据 */ export interface LevelProgress { levelId: number; completed: boolean; bestScore: number; bestTime: number; attempts: number; firstClearTime: number; lastPlayTime: number; rewards: RewardData[]; } /** * 背包数据 */ export interface InventoryData { weapons: { [weaponId: string]: WeaponData }; items: { [itemId: string]: ItemData }; materials: { [materialId: string]: number }; capacity: number; usedSlots: number; } /** * 武器数据 */ export interface WeaponData { weaponId: string; level: number; rarity: string; obtainTime: number; upgradeCount: number; isEquipped: boolean; } /** * 道具数据 */ export interface ItemData { itemId: string; count: number; obtainTime: number; lastUsedTime: number; } /** * 奖励数据 */ export interface RewardData { type: 'money' | 'coins' | 'diamonds' | 'weapon' | 'item'; id?: string; amount: number; obtainTime: number; source: string; // 获得来源:level_complete, daily_reward, shop_purchase等 } /** * 游戏统计数据 */ export interface GameStatistics { totalGamesPlayed: number; totalWins: number; totalLosses: number; totalScore: number; totalEnemiesDefeated: number; totalShotsfired: number; totalDamageDealt: number; totalTimePlayed: number; totalPlayTime: number; highestLevel: number; consecutiveWins: number; bestWinStreak: number; favoriteWeapon: string; weaponsUnlocked: number; itemsCollected: number; } /** * 玩家设置 */ export interface PlayerSettings { soundEnabled: boolean; musicEnabled: boolean; soundVolume: number; musicVolume: number; vibrationEnabled: boolean; autoSaveEnabled: boolean; language: string; graphics: 'low' | 'medium' | 'high'; newbieGuideCompleted: boolean; } /** * 存档管理器 * 负责玩家数据的保存、加载和管理 */ @ccclass('SaveDataManager') export class SaveDataManager { private static instance: SaveDataManager = null; private playerData: PlayerData = null; private initialized: boolean = false; private autoSaveInterval: number = 30; // 自动保存间隔(秒) private lastSaveTime: number = 0; // 私有属性 private weaponsConfig: { weapons: any[] } = null; private wallConfig: any = null; /** * 设置墙体配置(从MainUIController传递) */ public setWallConfig(config: any): void { this.wallConfig = config; console.log('[SaveDataManager] 接收到墙体配置:', this.wallConfig); } // 最近的奖励记录(用于UI显示) private lastRewards: {money: number, diamonds: number} = {money: 0, diamonds: 0}; // 存档文件键名 private readonly SAVE_KEY = 'pong_game_save_data'; private readonly BACKUP_KEY = 'pong_game_save_data_backup'; private readonly SETTINGS_KEY = 'pong_game_settings'; private constructor() { // 私有构造函数,确保单例模式 } public static getInstance(): SaveDataManager { if (SaveDataManager.instance === null) { SaveDataManager.instance = new SaveDataManager(); } return SaveDataManager.instance; } /** * 初始化存档管理器 */ public async initialize(): Promise { if (this.initialized) return; this.loadPlayerData(); await this.loadWeaponsConfig(); this.initialized = true; } /** * 加载武器配置 */ private async loadWeaponsConfig(): Promise { try { const bundleLoader = BundleLoader.getInstance(); const weaponData = await bundleLoader.loadDataJson('weapons'); if (!weaponData) { throw new Error('武器配置文件内容为空'); } this.weaponsConfig = weaponData.json as { weapons: any[] }; console.log('[SaveDataManager] 武器配置加载成功'); } catch (error) { console.error('[SaveDataManager] 加载武器配置失败:', error); this.weaponsConfig = { weapons: [] }; } } /** * 加载玩家数据 */ private loadPlayerData(): void { try { const savedData = sys.localStorage.getItem(this.SAVE_KEY); if (savedData) { const data = JSON.parse(savedData); this.playerData = this.validateAndMigrateData(data); this.playerData.lastPlayTime = Date.now(); } else { this.createNewPlayerData(); } } catch (error) { console.error('❌ 存档数据加载失败,尝试加载备份:', error); this.loadBackupData(); } } /** * 加载备份数据 */ private loadBackupData(): void { try { const backupData = sys.localStorage.getItem(this.BACKUP_KEY); if (backupData) { const data = JSON.parse(backupData); this.playerData = this.validateAndMigrateData(data); this.playerData.lastPlayTime = Date.now(); } else { this.createNewPlayerData(); } } catch (error) { console.error('❌ 备份数据加载失败,创建新存档:', error); this.createNewPlayerData(); } } /** * 创建新的玩家数据 */ private createNewPlayerData(): void { this.playerData = { playerId: this.generatePlayerId(), playerName: 'Player', createTime: Date.now(), lastPlayTime: Date.now(), totalPlayTime: 0, money: 0, // 初始局外金币 diamonds: 0, // 初始钻石 wallLevel: 1, // 初始墙体等级 currentLevel: 1, maxUnlockedLevel: 1, levelProgress: {}, inventory: { weapons: {}, items: {}, materials: {}, capacity: 50, usedSlots: 0 }, statistics: { totalGamesPlayed: 0, totalWins: 0, totalLosses: 0, totalScore: 0, totalEnemiesDefeated: 0, totalShotsfired: 0, totalDamageDealt: 0, totalTimePlayed: 0, totalPlayTime: 0, highestLevel: 1, consecutiveWins: 0, bestWinStreak: 0, favoriteWeapon: '', weaponsUnlocked: 0, itemsCollected: 0 }, settings: { soundEnabled: true, musicEnabled: true, soundVolume: 0.8, musicVolume: 0.6, vibrationEnabled: true, autoSaveEnabled: true, language: 'zh-CN', graphics: 'medium', newbieGuideCompleted: false } }; this.savePlayerData(); } /** * 验证和迁移数据(用于版本兼容) */ private validateAndMigrateData(data: any): PlayerData { // 数据迁移:将旧的coins字段迁移到money字段 if (data.coins !== undefined && data.money === undefined) { data.money = data.coins; console.log(`[SaveDataManager] 数据迁移: coins(${data.coins}) -> money(${data.money})`); delete data.coins; // 删除旧字段 } // 确保所有必要字段存在 const defaultData = this.createDefaultPlayerData(); return { ...defaultData, ...data, // 确保嵌套对象也被正确合并 inventory: { ...defaultData.inventory, ...data.inventory }, statistics: { ...defaultData.statistics, ...data.statistics }, settings: { ...defaultData.settings, ...data.settings } }; } /** * 创建默认玩家数据模板 */ private createDefaultPlayerData(): PlayerData { return { playerId: this.generatePlayerId(), playerName: 'Player', createTime: Date.now(), lastPlayTime: Date.now(), totalPlayTime: 0, money: 0, // 初始局外金钱 diamonds: 0, // 初始钻石 wallLevel: 1, // 初始墙体等级 currentLevel: 1, maxUnlockedLevel: 1, levelProgress: {}, inventory: { weapons: { // 默认解锁第一个武器(毛豆射手) 'pea_shooter': { weaponId: 'pea_shooter', level: 1, rarity: 'common', obtainTime: Date.now(), upgradeCount: 0, isEquipped: true } }, items: {}, materials: {}, capacity: 50, usedSlots: 0 }, statistics: { totalGamesPlayed: 0, totalWins: 0, totalLosses: 0, totalScore: 0, totalEnemiesDefeated: 0, totalShotsfired: 0, totalDamageDealt: 0, totalTimePlayed: 0, totalPlayTime: 0, highestLevel: 1, consecutiveWins: 0, bestWinStreak: 0, favoriteWeapon: 'pea_shooter', weaponsUnlocked: 1, itemsCollected: 0 }, settings: { soundEnabled: true, musicEnabled: true, soundVolume: 0.8, musicVolume: 0.6, vibrationEnabled: true, autoSaveEnabled: true, language: 'zh-CN', graphics: 'medium', newbieGuideCompleted: false } }; } /** * 保存玩家数据 */ public savePlayerData(force: boolean = false): void { if (!this.playerData) return; const currentTime = Date.now(); // 检查是否需要保存(避免频繁保存) if (!force && currentTime - this.lastSaveTime < 5000) { return; } try { // 更新最后保存时间 this.playerData.lastPlayTime = currentTime; // 创建备份 const currentData = sys.localStorage.getItem(this.SAVE_KEY); if (currentData) { sys.localStorage.setItem(this.BACKUP_KEY, currentData); } // 保存当前数据 const dataToSave = JSON.stringify(this.playerData); sys.localStorage.setItem(this.SAVE_KEY, dataToSave); this.lastSaveTime = currentTime; } catch (error) { console.error('❌ 玩家数据保存失败:', error); } } /** * 自动保存检查 */ public checkAutoSave(): void { if (!this.playerData || !this.playerData.settings.autoSaveEnabled) return; const currentTime = Date.now(); if (currentTime - this.lastSaveTime > this.autoSaveInterval * 1000) { this.savePlayerData(); } } // === 玩家基本信息管理 === public getPlayerData(): PlayerData { return this.playerData; } public getWallLevel(): number { return this.playerData?.wallLevel || 1; } public getWallHealth(): number { const wallLevel = this.getWallLevel(); if (this.wallConfig && this.wallConfig.wallConfig && this.wallConfig.wallConfig.healthByLevel) { return this.wallConfig.wallConfig.healthByLevel[wallLevel.toString()] || 200; } // 如果没有配置,返回默认值 return 200; } public getCurrentLevel(): number { return this.playerData?.currentLevel || 1; } /** * 设置当前关卡 */ public setCurrentLevel(level: number): void { if (!this.playerData) return; // 确保关卡在有效范围内 if (level >= 1 && level <= this.playerData.maxUnlockedLevel) { this.playerData.currentLevel = level; this.savePlayerData(); console.log(`[SaveDataManager] 当前关卡设置为: ${level}`); } else { console.warn(`[SaveDataManager] 无效的关卡设置: ${level},当前最大解锁关卡: ${this.playerData.maxUnlockedLevel}`); } } public getMaxUnlockedLevel(): number { return this.playerData?.maxUnlockedLevel || 1; } public getMoney(): number { return this.playerData?.money || 0; } // 保持向后兼容的方法 public getCoins(): number { return this.getMoney(); } public getDiamonds(): number { return this.playerData?.diamonds || 0; } // === 关卡进度管理 === /** * 完成关卡 */ public completeLevel(levelId: number, score: number, time: number): void { if (!this.playerData) return; // 更新关卡进度 if (!this.playerData.levelProgress[levelId]) { this.playerData.levelProgress[levelId] = { levelId: levelId, completed: false, bestScore: 0, bestTime: 0, attempts: 0, firstClearTime: 0, lastPlayTime: 0, rewards: [] }; } const progress = this.playerData.levelProgress[levelId]; progress.attempts += 1; progress.lastPlayTime = Date.now(); // 首次完成 if (!progress.completed) { progress.completed = true; progress.firstClearTime = Date.now(); // 解锁下一关 if (levelId === this.playerData.maxUnlockedLevel) { this.playerData.maxUnlockedLevel = levelId + 1; } } // 更新最佳记录 if (score > progress.bestScore) { progress.bestScore = score; } if (time > 0 && (progress.bestTime === 0 || time < progress.bestTime)) { progress.bestTime = time; } // 更新统计数据 this.playerData.statistics.totalGamesPlayed += 1; this.playerData.statistics.totalWins += 1; this.playerData.statistics.totalScore += score; this.playerData.statistics.consecutiveWins += 1; if (this.playerData.statistics.consecutiveWins > this.playerData.statistics.bestWinStreak) { this.playerData.statistics.bestWinStreak = this.playerData.statistics.consecutiveWins; } if (levelId > this.playerData.statistics.highestLevel) { this.playerData.statistics.highestLevel = levelId; } // 奖励处理已迁移到GameEnd.ts中 // this.giveCompletionRewards(levelId); this.savePlayerData(); } /** * 关卡失败 */ public failLevel(levelId: number): void { if (!this.playerData) return; // 更新关卡进度 if (!this.playerData.levelProgress[levelId]) { this.playerData.levelProgress[levelId] = { levelId: levelId, completed: false, bestScore: 0, bestTime: 0, attempts: 0, firstClearTime: 0, lastPlayTime: 0, rewards: [] }; } const progress = this.playerData.levelProgress[levelId]; progress.attempts += 1; progress.lastPlayTime = Date.now(); // 更新统计数据 this.playerData.statistics.totalGamesPlayed += 1; this.playerData.statistics.totalLosses += 1; this.playerData.statistics.consecutiveWins = 0; this.savePlayerData(); } /** * 获取关卡进度 */ public getLevelProgress(levelId: number): LevelProgress | null { return this.playerData?.levelProgress[levelId] || null; } /** * 检查关卡是否已解锁 */ public isLevelUnlocked(levelId: number): boolean { return levelId <= (this.playerData?.maxUnlockedLevel || 1); } /** * 检查关卡是否已完成 */ public isLevelCompleted(levelId: number): boolean { const progress = this.getLevelProgress(levelId); return progress?.completed || false; } // === 货币管理 === /** * 添加局外钞票 */ public addMoney(amount: number, source: string = 'unknown'): boolean { if (!this.playerData || amount <= 0) return false; this.playerData.money += amount; this.addReward('money', '', amount, source); // 触发货币变化事件 EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED); return true; } // 保持向后兼容的方法 public addCoins(amount: number, source: string = 'unknown'): boolean { return this.addMoney(amount, source); } /** * 消费局外钞票 */ public spendMoney(amount: number): boolean { if (!this.playerData || amount <= 0) { console.log(`[SaveDataManager] spendMoney失败 - 无效参数: amount=${amount}, playerData=${!!this.playerData}`); return false; } if (this.playerData.money < amount) { console.log(`[SaveDataManager] spendMoney失败 - 钞票不足: 需要=${amount}, 当前=${this.playerData.money}`); return false; } const moneyBefore = this.playerData.money; this.playerData.money -= amount; console.log(`[SaveDataManager] spendMoney成功 - 消费: ${amount}, 之前: ${moneyBefore}, 之后: ${this.playerData.money}`); // 触发货币变化事件 EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED); return true; } /** * 添加钻石 */ public addDiamonds(amount: number, source: string = 'unknown'): boolean { if (!this.playerData || amount <= 0) return false; this.playerData.diamonds += amount; this.addReward('diamonds', '', amount, source); // 触发货币变化事件 EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED); return true; } /** * 消费钻石 */ public spendDiamonds(amount: number): boolean { if (!this.playerData || amount <= 0 || this.playerData.diamonds < amount) { return false; } this.playerData.diamonds -= amount; // 触发货币变化事件 EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED); return true; } // === 墙体等级管理 === /** * 升级墙体等级 */ public upgradeWallLevel(): boolean { if (!this.playerData) return false; this.playerData.wallLevel += 1; this.savePlayerData(true); return true; } // === 道具和武器管理 === /** * 添加武器 */ public addWeapon(weaponId: string, rarity: string = 'common', initialLevel: number = 0): boolean { if (!this.playerData) return false; if (!this.playerData.inventory.weapons[weaponId]) { this.playerData.inventory.weapons[weaponId] = { weaponId: weaponId, level: initialLevel, // 初始等级可配置,0表示未解锁,1表示已解锁 rarity: rarity, obtainTime: Date.now(), upgradeCount: 0, isEquipped: false }; // 只有解锁的武器才计入统计 if (initialLevel > 0) { this.playerData.statistics.weaponsUnlocked += 1; this.addReward('weapon', weaponId, 1, 'drop'); } return true; } return false; } /** * 获取武器数据 */ public getWeapon(weaponId: string): WeaponData | null { if (!this.playerData) return null; return this.playerData.inventory.weapons[weaponId] || null; } /** * 获取所有武器数据 */ public getAllWeapons(): { [weaponId: string]: WeaponData } { if (!this.playerData) return {}; return this.playerData.inventory.weapons; } /** * 升级武器 */ public upgradeWeapon(weaponId: string): boolean { if (!this.playerData) return false; const weapon = this.playerData.inventory.weapons[weaponId]; if (!weapon || weapon.level === 0) return false; // 0级武器需要先解锁 const cost = this.getWeaponUpgradeCost(weaponId); if (!this.spendMoney(cost)) return false; weapon.level += 1; weapon.upgradeCount += 1; return true; } /** * 获取武器升级费用 */ public getWeaponUpgradeCost(weaponId: string): number { const weapon = this.getWeapon(weaponId); if (!weapon || weapon.level === 0) return 0; // 0级武器需要解锁,不是升级 // 从武器配置中获取升级费用 if (this.weaponsConfig && this.weaponsConfig.weapons) { const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === weaponId); if (weaponConfig && weaponConfig.upgradeConfig && weaponConfig.upgradeConfig.levels) { const levelConfig = weaponConfig.upgradeConfig.levels[weapon.level.toString()]; if (levelConfig && levelConfig.cost) { return levelConfig.cost; } } } // 如果配置不存在,使用默认公式作为后备 return 25 * weapon.level; } /** * 检查是否可以升级武器 */ public canUpgradeWeapon(weaponId: string): boolean { const weapon = this.getWeapon(weaponId); if (!weapon || weapon.level === 0) return false; // 0级武器需要先解锁 const cost = this.getWeaponUpgradeCost(weaponId); return this.getMoney() >= cost; } /** * 解锁武器(将等级从0提升到1) */ public unlockWeapon(weaponId: string): boolean { if (!this.playerData) return false; // 如果武器不存在,先添加(添加时设置为解锁状态) if (!this.playerData.inventory.weapons[weaponId]) { this.addWeapon(weaponId, 'common', 1); return true; // 添加武器即表示解锁成功 } const weapon = this.playerData.inventory.weapons[weaponId]; if (!weapon) return false; // 如果武器存在但未解锁(level为0),则解锁它 if (weapon.level === 0) { weapon.level = 1; this.playerData.statistics.weaponsUnlocked += 1; this.addReward('weapon', weaponId, 1, 'unlock'); return true; } // 武器已经存在且等级>=1,表示已解锁 return weapon.level >= 1; } /** * 检查武器是否已解锁 */ public isWeaponUnlocked(weaponId: string): boolean { // 根据关卡进度判断武器是否应该解锁 const requiredLevel = this.getWeaponUnlockLevel(weaponId); const maxUnlockedLevel = this.getMaxUnlockedLevel(); console.log(`[PreviewInEditor] 检查武器解锁: ${weaponId}, 需要关卡: ${requiredLevel}, 当前最大解锁关卡: ${maxUnlockedLevel}`); return maxUnlockedLevel >= requiredLevel; } /** * 检查指定关卡是否会触发新武器解锁(基于配置) */ public hasNewWeaponUnlockAtLevel(level: number): boolean { if (!this.weaponsConfig || !this.weaponsConfig.weapons) return false; for (const weapon of this.weaponsConfig.weapons) { if (weapon.unlockLevel === level) { const weaponData = this.getWeapon(weapon.id); const isUnlocked = weaponData && weaponData.level > 0; if (!isUnlocked) { return true; } } } return false; } /** * 获取武器解锁所需的关卡等级 */ private getWeaponUnlockLevel(weaponId: string): number { // 从武器配置中读取解锁等级 if (this.weaponsConfig && this.weaponsConfig.weapons) { const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === weaponId); if (weaponConfig && weaponConfig.unlockLevel !== undefined) { return weaponConfig.unlockLevel; } } // 如果配置不存在,返回默认值1 return 1; } /** * 添加道具 */ public addItem(itemId: string, count: number = 1): boolean { if (!this.playerData || count <= 0) return false; if (!this.playerData.inventory.items[itemId]) { this.playerData.inventory.items[itemId] = { itemId: itemId, count: 0, obtainTime: Date.now(), lastUsedTime: 0 }; } this.playerData.inventory.items[itemId].count += count; this.playerData.statistics.itemsCollected += count; this.addReward('item', itemId, count, 'drop'); return true; } /** * 使用道具 */ public useItem(itemId: string, count: number = 1): boolean { if (!this.playerData || count <= 0) return false; const item = this.playerData.inventory.items[itemId]; if (!item || item.count < count) { return false; } item.count -= count; item.lastUsedTime = Date.now(); if (item.count === 0) { delete this.playerData.inventory.items[itemId]; } return true; } // === 奖励管理 === /** * 添加奖励记录 */ private addReward(type: RewardData['type'], id: string, amount: number, source: string): void { if (!this.playerData) return; const reward: RewardData = { type: type, id: id, amount: amount, obtainTime: Date.now(), source: source }; // 这里可以添加到全局奖励历史记录中 // 暂时不实现,避免数据过大 } /** * 从JSON配置文件获取关卡奖励数据 */ public async getLevelRewardsFromConfig(levelId: number): Promise<{money: number, diamonds: number} | null> { try { console.log(`[SaveDataManager] 开始获取关卡${levelId}的奖励配置`); // 由于不支持动态导入,改为直接导入 const configManager = LevelConfigManager.getInstance(); if (!configManager) { console.warn(`LevelConfigManager未初始化,使用默认奖励`); return null; } const levelConfig = await configManager.getLevelConfig(levelId); if (levelConfig && levelConfig.levelSettings && (levelConfig.levelSettings as any).rewards) { const rewards = (levelConfig.levelSettings as any).rewards; console.log(`[SaveDataManager] 从LevelConfigManager获取到奖励:`, rewards); return { money: rewards.coins || 0, diamonds: rewards.diamonds || 0 }; } // 如果JSON中没有奖励配置,尝试使用BundleLoader从data Bundle加载 const jsonPath = `levels/Level${levelId}`; console.log(`[SaveDataManager] 尝试使用BundleLoader从data Bundle加载: ${jsonPath}`); try { const bundleLoader = BundleLoader.getInstance(); const asset = await bundleLoader.loadDataJson(jsonPath); if (!asset || !asset.json) { console.warn(`无法加载关卡${levelId}的JSON配置`); return null; } const jsonData = asset.json; console.log(`[SaveDataManager] JSON数据:`, jsonData); // 修复字段名称映射:直接从JSON根级别读取coinReward和diamondReward if (jsonData && (jsonData.coinReward !== undefined || jsonData.diamondReward !== undefined)) { const rewardData = { money: jsonData.coinReward || 0, diamonds: jsonData.diamondReward || 0 }; return rewardData; } else if (jsonData && jsonData.rewards) { // 兼容嵌套在rewards对象中的情况 const rewardData = { money: jsonData.rewards.coins || jsonData.rewards.coinReward || 0, diamonds: jsonData.rewards.diamonds || jsonData.rewards.diamondReward || 0 }; console.log(`[SaveDataManager] 从JSON.rewards获取到奖励:`, rewardData); return rewardData; } else { console.warn(`[SaveDataManager] JSON中未找到奖励配置`); return null; } } catch (error) { console.warn(`使用BundleLoader加载关卡${levelId}配置失败:`, error); return null; } } catch (error) { console.error(`获取关卡${levelId}奖励配置失败:`, error); return null; } } /** * 给予关卡完成奖励(从JSON配置获取) */ public async giveCompletionRewards(levelId: number): Promise { console.log(`[SaveDataManager] 开始给予关卡${levelId}完成奖励`); // 尝试从JSON配置文件获取奖励数据 const configRewards = await this.getLevelRewardsFromConfig(levelId); console.log(`[SaveDataManager] 获取到的配置奖励:`, configRewards); let actualCoins = 0; let actualDiamonds = 0; if (configRewards) { // 使用JSON配置中的奖励数据 if (configRewards.money > 0) { this.addMoney(configRewards.money, `level_${levelId}_complete`); actualCoins = configRewards.money; console.log(`[SaveDataManager] 添加钞票: ${configRewards.money}`); } if (configRewards.diamonds > 0) { this.addDiamonds(configRewards.diamonds, `level_${levelId}_complete`); actualDiamonds = configRewards.diamonds; console.log(`[SaveDataManager] 添加钻石: ${configRewards.diamonds}`); } } else { console.warn(`[SaveDataManager] 未获取到配置奖励,使用默认值0`); } // 特殊关卡额外奖励(里程碑奖励) // if (levelId % 10 === 0) { // this.addGems(1, `level_${levelId}_milestone`); // } // 存储最近的奖励记录 this.lastRewards = {money: actualCoins, diamonds: actualDiamonds}; console.log(`[SaveDataManager] 最终奖励记录:`, this.lastRewards); } /** * 根据波数比例给予失败奖励 */ public async giveFailureRewards(levelId: number, completedWaves: number, totalWaves: number): Promise { console.log(`[SaveDataManager] 计算失败奖励 - 关卡: ${levelId}, 完成波数: ${completedWaves}/${totalWaves}`); if (totalWaves <= 0) { console.warn('[SaveDataManager] 总波数无效,重置奖励为0'); this.lastRewards = {money: 0, diamonds: 0}; return; } // 如果完成波数为0,则不给予任何奖励 if (completedWaves <= 0) { console.log('[SaveDataManager] 完成波数为0,不给予任何奖励'); this.lastRewards = {money: 0, diamonds: 0}; return; } const actualCompletedWaves = Math.max(completedWaves, 0); const waveRatio = actualCompletedWaves / totalWaves; console.log(`[SaveDataManager] 波数完成情况: ${actualCompletedWaves}/${totalWaves} = ${(waveRatio * 100).toFixed(1)}%`); // 获取完整奖励数据 const configRewards = await this.getLevelRewardsFromConfig(levelId); let actualCoins = 0; let actualDiamonds = 0; if (configRewards) { // 基于JSON配置计算比例奖励(取整) const partialCoins = Math.floor(configRewards.money * waveRatio); const partialDiamonds = Math.floor(configRewards.diamonds * waveRatio); console.log(`[SaveDataManager] 基于配置计算奖励 - 原始钞票: ${configRewards.money}, 原始钻石: ${configRewards.diamonds}`); console.log(`[SaveDataManager] 计算出的失败奖励 - 钞票: ${partialCoins}, 钻石: ${partialDiamonds}`); if (partialCoins > 0) { this.addMoney(partialCoins, `level_${levelId}_partial_${actualCompletedWaves}/${totalWaves}`); actualCoins = partialCoins; } if (partialDiamonds > 0) { this.addDiamonds(partialDiamonds, `level_${levelId}_partial_${actualCompletedWaves}/${totalWaves}`); actualDiamonds = partialDiamonds; } } else { // 回退到默认计算 const baseCoins = levelId * 50; const partialCoins = Math.floor(baseCoins * waveRatio); console.log(`[SaveDataManager] 使用默认计算 - 基础钞票: ${baseCoins}, 计算出的失败奖励: ${partialCoins}`); if (partialCoins > 0) { this.addMoney(partialCoins, `level_${levelId}_partial_${actualCompletedWaves}/${totalWaves}`); actualCoins = partialCoins; } } console.log(`[SaveDataManager] 最终失败奖励 - 钞票: ${actualCoins}, 钻石: ${actualDiamonds}`); // 存储最近的奖励记录 this.lastRewards = {money: actualCoins, diamonds: actualDiamonds}; } /** * 获取最近的奖励记录(用于UI显示) */ public getLastRewards(): {money: number, diamonds: number} { return {...this.lastRewards}; } // === 统计数据更新 === public updateStatistic(key: keyof GameStatistics, value: number): void { if (!this.playerData) return; if (typeof this.playerData.statistics[key] === 'number') { (this.playerData.statistics[key] as number) += value; } } /** * 设置收藏武器 */ public setFavoriteWeapon(weaponId: string): void { if (!this.playerData) return; this.playerData.statistics.favoriteWeapon = weaponId; this.savePlayerData(); } /** * 获取收藏武器 */ public getFavoriteWeapon(): string { return this.playerData?.statistics.favoriteWeapon || ''; } // === 设置管理 === public updateSetting(key: K, value: PlayerSettings[K]): void { if (!this.playerData) return; this.playerData.settings[key] = value; this.savePlayerData(); } public getSetting(key: K): PlayerSettings[K] { return this.playerData?.settings[key]; } // === 工具方法 === /** * 生成唯一玩家ID */ private generatePlayerId(): string { return `player_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } /** * 重置所有数据 */ public resetAllData(): void { sys.localStorage.removeItem(this.SAVE_KEY); sys.localStorage.removeItem(this.BACKUP_KEY); this.createNewPlayerData(); } /** * 导出存档数据(用于调试) */ public exportSaveData(): string { return JSON.stringify(this.playerData, null, 2); } /** * 导入存档数据(用于调试) */ public importSaveData(dataString: string): boolean { try { const data = JSON.parse(dataString); this.playerData = this.validateAndMigrateData(data); this.savePlayerData(true); return true; } catch (error) { console.error('❌ 存档数据导入失败:', error); return false; } } /** * 获取存档摘要信息 */ public getSaveSummary(): string { if (!this.playerData) return '无存档数据'; return `墙体等级: ${this.playerData.wallLevel} | ` + `当前关卡: ${this.playerData.currentLevel} | ` + `最高关卡: ${this.playerData.maxUnlockedLevel} | ` + `局外钞票: ${this.playerData.money} | ` + `钻石: ${this.playerData.diamonds} | ` + `游戏次数: ${this.playerData.statistics.totalGamesPlayed}`; } }