|
|
@@ -1,5 +1,6 @@
|
|
|
import { _decorator, sys, resources, JsonAsset } from 'cc';
|
|
|
import { LevelConfigManager } from './LevelConfigManager';
|
|
|
+import EventBus, { GameEvents } from '../Core/EventBus';
|
|
|
const { ccclass, property } = _decorator;
|
|
|
|
|
|
/**
|
|
|
@@ -14,9 +15,8 @@ export interface PlayerData {
|
|
|
totalPlayTime: number;
|
|
|
|
|
|
// 货币系统
|
|
|
- coins: number; // 金币
|
|
|
+ money: number; // 局外金币
|
|
|
diamonds: number; // 钻石
|
|
|
- gems: number; // 宝石
|
|
|
|
|
|
// 墙体等级系统
|
|
|
wallLevel: number; // 墙体等级
|
|
|
@@ -88,7 +88,7 @@ export interface ItemData {
|
|
|
* 奖励数据
|
|
|
*/
|
|
|
export interface RewardData {
|
|
|
- type: 'coins' | 'diamonds' | 'gems' | 'weapon' | 'item';
|
|
|
+ type: 'money' | 'coins' | 'diamonds' | 'weapon' | 'item';
|
|
|
id?: string;
|
|
|
amount: number;
|
|
|
obtainTime: number;
|
|
|
@@ -143,7 +143,7 @@ export class SaveDataManager {
|
|
|
private lastSaveTime: number = 0;
|
|
|
|
|
|
// 最近的奖励记录(用于UI显示)
|
|
|
- private lastRewards: {coins: number, diamonds: number} = {coins: 0, diamonds: 0};
|
|
|
+ private lastRewards: {money: number, diamonds: number} = {money: 0, diamonds: 0};
|
|
|
|
|
|
// 存档文件键名
|
|
|
private readonly SAVE_KEY = 'pong_game_save_data';
|
|
|
@@ -222,9 +222,8 @@ export class SaveDataManager {
|
|
|
lastPlayTime: Date.now(),
|
|
|
totalPlayTime: 0,
|
|
|
|
|
|
- coins: 45, // 初始金币
|
|
|
+ money: 20, // 初始局外金币
|
|
|
diamonds: 0, // 初始钻石
|
|
|
- gems: 0,
|
|
|
|
|
|
wallLevel: 1, // 初始墙体等级
|
|
|
wallBaseHealth: 100, // 初始墙体基础血量
|
|
|
@@ -277,6 +276,13 @@ export class SaveDataManager {
|
|
|
* 验证和迁移数据(用于版本兼容)
|
|
|
*/
|
|
|
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();
|
|
|
|
|
|
@@ -300,9 +306,8 @@ export class SaveDataManager {
|
|
|
createTime: Date.now(),
|
|
|
lastPlayTime: Date.now(),
|
|
|
totalPlayTime: 0,
|
|
|
- coins: 2000, // 增加初始金币用于测试升级功能
|
|
|
- diamonds: 50,
|
|
|
- gems: 0,
|
|
|
+ money: 0, // 初始局外金币
|
|
|
+ diamonds: 0,
|
|
|
wallLevel: 1, // 初始墙体等级
|
|
|
wallBaseHealth: 100, // 初始墙体基础血量
|
|
|
currentLevel: 1,
|
|
|
@@ -433,17 +438,20 @@ export class SaveDataManager {
|
|
|
return this.playerData?.maxUnlockedLevel || 1;
|
|
|
}
|
|
|
|
|
|
+ public getMoney(): number {
|
|
|
+ return this.playerData?.money || 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保持向后兼容的方法
|
|
|
public getCoins(): number {
|
|
|
- return this.playerData?.coins || 0;
|
|
|
+ return this.getMoney();
|
|
|
}
|
|
|
|
|
|
public getDiamonds(): number {
|
|
|
return this.playerData?.diamonds || 0;
|
|
|
}
|
|
|
|
|
|
- public getGems(): number {
|
|
|
- return this.playerData?.gems || 0;
|
|
|
- }
|
|
|
+
|
|
|
|
|
|
// === 关卡进度管理 ===
|
|
|
|
|
|
@@ -568,29 +576,54 @@ export class SaveDataManager {
|
|
|
// === 货币管理 ===
|
|
|
|
|
|
/**
|
|
|
- * 添加金币
|
|
|
+ * 添加局外金币
|
|
|
*/
|
|
|
- public addCoins(amount: number, source: string = 'unknown'): boolean {
|
|
|
+ public addMoney(amount: number, source: string = 'unknown'): boolean {
|
|
|
if (!this.playerData || amount <= 0) return false;
|
|
|
|
|
|
- this.playerData.coins += amount;
|
|
|
- this.addReward('coins', '', amount, source);
|
|
|
+ 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 spendCoins(amount: number): boolean {
|
|
|
- if (!this.playerData || amount <= 0 || this.playerData.coins < amount) {
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
- this.playerData.coins -= amount;
|
|
|
+ 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 spendCoins(amount: number): boolean {
|
|
|
+ return this.spendMoney(amount);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 添加钻石
|
|
|
*/
|
|
|
@@ -600,6 +633,9 @@ export class SaveDataManager {
|
|
|
this.playerData.diamonds += amount;
|
|
|
this.addReward('diamonds', '', amount, source);
|
|
|
|
|
|
+ // 触发货币变化事件
|
|
|
+ EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -612,21 +648,15 @@ export class SaveDataManager {
|
|
|
}
|
|
|
|
|
|
this.playerData.diamonds -= amount;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加宝石
|
|
|
- */
|
|
|
- public addGems(amount: number, source: string = 'unknown'): boolean {
|
|
|
- if (!this.playerData || amount <= 0) return false;
|
|
|
|
|
|
- this.playerData.gems += amount;
|
|
|
- this.addReward('gems', '', amount, source);
|
|
|
+ // 触发货币变化事件
|
|
|
+ EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
// === 墙体等级管理 ===
|
|
|
|
|
|
/**
|
|
|
@@ -679,7 +709,7 @@ export class SaveDataManager {
|
|
|
if (this.playerData.wallLevel >= 5) return false;
|
|
|
|
|
|
const cost = this.getWallUpgradeCost();
|
|
|
- return this.playerData.coins >= cost;
|
|
|
+ return this.playerData.money >= cost;
|
|
|
}
|
|
|
|
|
|
// === 道具和武器管理 ===
|
|
|
@@ -693,7 +723,7 @@ export class SaveDataManager {
|
|
|
if (!this.playerData.inventory.weapons[weaponId]) {
|
|
|
this.playerData.inventory.weapons[weaponId] = {
|
|
|
weaponId: weaponId,
|
|
|
- level: 0, // 初始等级为0,需要解锁
|
|
|
+ level: 1, // 初始等级为1,符合游戏设计
|
|
|
rarity: rarity,
|
|
|
obtainTime: Date.now(),
|
|
|
upgradeCount: 0,
|
|
|
@@ -732,10 +762,10 @@ export class SaveDataManager {
|
|
|
if (!this.playerData) return false;
|
|
|
|
|
|
const weapon = this.playerData.inventory.weapons[weaponId];
|
|
|
- if (!weapon) return false;
|
|
|
+ if (!weapon || weapon.level === 0) return false; // 0级武器需要先解锁
|
|
|
|
|
|
const cost = this.getWeaponUpgradeCost(weaponId);
|
|
|
- if (!this.spendCoins(cost)) return false;
|
|
|
+ if (!this.spendMoney(cost)) return false;
|
|
|
|
|
|
weapon.level += 1;
|
|
|
weapon.upgradeCount += 1;
|
|
|
@@ -748,12 +778,10 @@ export class SaveDataManager {
|
|
|
*/
|
|
|
public getWeaponUpgradeCost(weaponId: string): number {
|
|
|
const weapon = this.getWeapon(weaponId);
|
|
|
- if (!weapon) return 0;
|
|
|
+ if (!weapon || weapon.level === 0) return 0; // 0级武器需要解锁,不是升级
|
|
|
|
|
|
- // 基础费用 + 等级递增费用
|
|
|
- const baseCost = 150;
|
|
|
- const levelMultiplier = weapon.level + 1;
|
|
|
- return baseCost * levelMultiplier;
|
|
|
+ // 金币消耗:升级消耗金币 = 25 × 升级前武器等级
|
|
|
+ return 25 * weapon.level;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -761,10 +789,10 @@ export class SaveDataManager {
|
|
|
*/
|
|
|
public canUpgradeWeapon(weaponId: string): boolean {
|
|
|
const weapon = this.getWeapon(weaponId);
|
|
|
- if (!weapon) return false;
|
|
|
+ if (!weapon || weapon.level === 0) return false; // 0级武器需要先解锁
|
|
|
|
|
|
const cost = this.getWeaponUpgradeCost(weaponId);
|
|
|
- return this.getCoins() >= cost;
|
|
|
+ return this.getMoney() >= cost;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -773,34 +801,28 @@ export class SaveDataManager {
|
|
|
public unlockWeapon(weaponId: string): boolean {
|
|
|
if (!this.playerData) return false;
|
|
|
|
|
|
- // 如果武器不存在,先添加
|
|
|
+ // 如果武器不存在,先添加(添加时已经是等级1)
|
|
|
if (!this.playerData.inventory.weapons[weaponId]) {
|
|
|
this.addWeapon(weaponId);
|
|
|
+ return true; // 添加武器即表示解锁成功
|
|
|
}
|
|
|
|
|
|
const weapon = this.playerData.inventory.weapons[weaponId];
|
|
|
- if (!weapon || weapon.level > 0) return false;
|
|
|
-
|
|
|
- // 解锁费用固定为100金币
|
|
|
- const unlockCost = 100;
|
|
|
- if (!this.spendCoins(unlockCost)) return false;
|
|
|
+ if (!weapon) return false;
|
|
|
|
|
|
- weapon.level = 1;
|
|
|
- return true;
|
|
|
+ // 武器已经存在且等级>=1,表示已解锁
|
|
|
+ return weapon.level >= 1;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 检查武器是否已解锁
|
|
|
*/
|
|
|
public isWeaponUnlocked(weaponId: string): boolean {
|
|
|
- const weapon = this.getWeapon(weaponId);
|
|
|
- if (weapon && weapon.level > 0) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
// 根据关卡进度判断武器是否应该解锁
|
|
|
const requiredLevel = this.getWeaponUnlockLevel(weaponId);
|
|
|
- return this.getMaxUnlockedLevel() >= requiredLevel;
|
|
|
+ const maxUnlockedLevel = this.getMaxUnlockedLevel();
|
|
|
+ console.log(`[PreviewInEditor] 检查武器解锁: ${weaponId}, 需要关卡: ${requiredLevel}, 当前最大解锁关卡: ${maxUnlockedLevel}`);
|
|
|
+ return maxUnlockedLevel >= requiredLevel;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -948,7 +970,7 @@ export class SaveDataManager {
|
|
|
if (configRewards) {
|
|
|
// 使用JSON配置中的奖励数据
|
|
|
if (configRewards.coins > 0) {
|
|
|
- this.addCoins(configRewards.coins, `level_${levelId}_complete`);
|
|
|
+ this.addMoney(configRewards.coins, `level_${levelId}_complete`);
|
|
|
actualCoins = configRewards.coins;
|
|
|
}
|
|
|
if (configRewards.diamonds > 0) {
|
|
|
@@ -958,12 +980,12 @@ export class SaveDataManager {
|
|
|
}
|
|
|
|
|
|
// 特殊关卡额外奖励(里程碑奖励)
|
|
|
- if (levelId % 10 === 0) {
|
|
|
- this.addGems(1, `level_${levelId}_milestone`);
|
|
|
- }
|
|
|
+ // if (levelId % 10 === 0) {
|
|
|
+ // this.addGems(1, `level_${levelId}_milestone`);
|
|
|
+ // }
|
|
|
|
|
|
// 存储最近的奖励记录
|
|
|
- this.lastRewards = {coins: actualCoins, diamonds: actualDiamonds};
|
|
|
+ this.lastRewards = {money: actualCoins, diamonds: actualDiamonds};
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -972,7 +994,7 @@ export class SaveDataManager {
|
|
|
public async giveFailureRewards(levelId: number, completedWaves: number, totalWaves: number): Promise<void> {
|
|
|
if (completedWaves <= 0 || totalWaves <= 0) {
|
|
|
// 重置最近奖励为0
|
|
|
- this.lastRewards = {coins: 0, diamonds: 0};
|
|
|
+ this.lastRewards = {money: 0, diamonds: 0};
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -991,7 +1013,7 @@ export class SaveDataManager {
|
|
|
const partialDiamonds = Math.floor(configRewards.diamonds * waveRatio);
|
|
|
|
|
|
if (partialCoins > 0) {
|
|
|
- this.addCoins(partialCoins, `level_${levelId}_partial_${completedWaves}/${totalWaves}`);
|
|
|
+ this.addMoney(partialCoins, `level_${levelId}_partial_${completedWaves}/${totalWaves}`);
|
|
|
actualCoins = partialCoins;
|
|
|
}
|
|
|
if (partialDiamonds > 0) {
|
|
|
@@ -1004,19 +1026,19 @@ export class SaveDataManager {
|
|
|
const partialCoins = Math.floor(baseCoins * waveRatio);
|
|
|
|
|
|
if (partialCoins > 0) {
|
|
|
- this.addCoins(partialCoins, `level_${levelId}_partial_${completedWaves}/${totalWaves}`);
|
|
|
+ this.addMoney(partialCoins, `level_${levelId}_partial_${completedWaves}/${totalWaves}`);
|
|
|
actualCoins = partialCoins;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 存储最近的奖励记录
|
|
|
- this.lastRewards = {coins: actualCoins, diamonds: actualDiamonds};
|
|
|
+ this.lastRewards = {money: actualCoins, diamonds: actualDiamonds};
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取最近的奖励记录(用于UI显示)
|
|
|
*/
|
|
|
- public getLastRewards(): {coins: number, diamonds: number} {
|
|
|
+ public getLastRewards(): {money: number, diamonds: number} {
|
|
|
return {...this.lastRewards};
|
|
|
}
|
|
|
|
|
|
@@ -1092,7 +1114,7 @@ export class SaveDataManager {
|
|
|
return `墙体等级: ${this.playerData.wallLevel} | ` +
|
|
|
`当前关卡: ${this.playerData.currentLevel} | ` +
|
|
|
`最高关卡: ${this.playerData.maxUnlockedLevel} | ` +
|
|
|
- `金币: ${this.playerData.coins} | ` +
|
|
|
+ `局外金币: ${this.playerData.money} | ` +
|
|
|
`钻石: ${this.playerData.diamonds} | ` +
|
|
|
`游戏次数: ${this.playerData.statistics.totalGamesPlayed}`;
|
|
|
}
|