Browse Source

武器升级系统完成

181404010226 4 months ago
parent
commit
e58992a598

+ 0 - 85
Toast事件机制修改说明.md

@@ -1,85 +0,0 @@
-# Toast事件机制修改说明
-
-## 修改概述
-
-本次修改将Toast提示系统从直接节点操作改为事件驱动机制,提高了代码的解耦性和可维护性。
-
-## 主要修改内容
-
-### 1. EventBus事件扩展
-
-在 `assets/scripts/Core/EventBus.ts` 中添加了新的Toast事件:
-
-```typescript
-// Toast提示事件
-SHOW_TOAST = 'SHOW_TOAST',
-HIDE_TOAST = 'HIDE_TOAST'
-```
-
-### 2. ToastAni动画组件
-
-创建了 `assets/scripts/Animations/ToastAni.ts` 文件,实现了Toast的滑动动画效果:
-
-- **滑入动画**:从屏幕左边中间位置滑入到屏幕中央
-- **滑出动画**:从屏幕中央滑出到屏幕右边外侧
-- **位置重置**:动画完成后自动重置到初始位置
-- **事件监听**:监听 `SHOW_TOAST` 和 `HIDE_TOAST` 事件
-
-### 3. GameBlockSelection.ts 修改
-
-- 移除了 `toastNode` 属性的直接引用
-- 修改 `showInsufficientCoinsUI()` 方法使用事件机制
-- 修改 `showNoPlacedBlocksToast()` 方法使用事件机制
-
-### 4. EnemyController.ts 修改
-
-- 移除了 `toastPrefab` 属性
-- 修改 `showStartWavePromptUI()` 方法使用事件机制
-- 简化了波次提示的显示逻辑
-
-## 使用方法
-
-### 显示Toast提示
-
-```typescript
-// 显示Toast消息
-EventBus.getInstance().emit(GameEvents.SHOW_TOAST, {
-    message: '这是提示消息',
-    duration: 3.0  // 可选,默认3秒
-});
-```
-
-### 手动隐藏Toast
-
-```typescript
-// 手动隐藏Toast
-EventBus.getInstance().emit(GameEvents.HIDE_TOAST);
-```
-
-## 动画特性
-
-1. **固定位置**:Toast始终从屏幕左边中间位置进入,从右边中间滑出
-2. **不受Camera影响**:动画位置基于Canvas坐标系,不受Camera移动影响
-3. **自动管理**:节点默认为active状态,无需手动激活/隐藏
-4. **防重复**:动画进行中时会忽略新的显示请求
-5. **自动重置**:动画完成后自动重置到初始位置
-
-## 配置要求
-
-1. Canvas/Toast节点需要添加 `ToastAni` 组件
-2. Toast节点的子节点 `label` 需要有 `cc.Label` 组件
-3. 确保EventBus正常工作
-
-## 优势
-
-1. **解耦合**:各模块不再需要直接引用Toast节点
-2. **统一管理**:所有Toast显示通过事件系统统一管理
-3. **易扩展**:可以轻松添加新的Toast类型和样式
-4. **更好的动画**:提供了流畅的滑入滑出动画效果
-5. **减少依赖**:移除了对预制体的直接依赖
-
-## 注意事项
-
-1. 需要确保Canvas/Toast节点存在并正确配置ToastAni组件
-2. 事件参数中的message为必需参数,duration为可选参数
-3. 动画期间会忽略新的显示请求,避免动画冲突

+ 2 - 3
assets/resources/data/player_data.json

@@ -2,9 +2,8 @@
   "playerId": "gid-20240711-001",
   "createTime": 1720634200000,
   "wallLevel": 1,
-  "coins": 1230,
-  "diamonds": 75,
-  "gems": 6,
+  "money": 1230,
+  "diamonds": 0,
 
   "currentLevel": 1,
   "maxUnlockedLevel": 1,

+ 1 - 1
assets/resources/prefabs/Upgrade/Unlock.prefab

@@ -653,7 +653,7 @@
       "b": 255,
       "a": 255
     },
-    "_string": "6",
+    "_string": "1",
     "_horizontalAlign": 1,
     "_verticalAlign": 1,
     "_actualFontSize": 26,

+ 6 - 3
assets/scripts/Animations/MoneyAni.ts

@@ -1,6 +1,7 @@
 import { _decorator, Component, Node, Vec3, tween, instantiate, Prefab, math, Label, director } from 'cc';
 import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 import { TopBarController } from '../FourUI/TopBarController';
+import EventBus, { GameEvents } from '../Core/EventBus';
 const { ccclass, property } = _decorator;
 
 /**
@@ -130,8 +131,9 @@ export class MoneyAni extends Component {
                     coinsCompleted++;
                     if (coinsCompleted >= coinCount) {
                         // 所有金币动画完成,更新数据
-                        this.saveDataManager.addCoins(amount, 'level_reward');
-                        TopBarController.updateTopBarUI();
+                        this.saveDataManager.addMoney(amount, 'level_reward');
+                        // 通过事件系统通知UI更新
+            EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
                         if (onComplete) onComplete();
                     }
                 });
@@ -174,7 +176,8 @@ export class MoneyAni extends Component {
                     if (diamondsCompleted >= diamondCount) {
                         // 所有钻石动画完成,更新数据
                         this.saveDataManager.addDiamonds(amount, 'level_reward');
-                        TopBarController.updateTopBarUI();
+                        // 通过事件系统通知UI更新
+                        EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
                         if (onComplete) onComplete();
                     }
                 });

+ 5 - 1
assets/scripts/Animations/ToastAni.ts

@@ -8,6 +8,7 @@ export class ToastAni extends Component {
     
     private originalPosition: Vec3 = new Vec3();
     private isAnimating: boolean = false;
+    private currentDuration: number = 2.0; // 默认显示时长(秒)
     
     onLoad() {
         // 保存初始位置
@@ -30,6 +31,9 @@ export class ToastAni extends Component {
             return;
         }
         
+        // 设置显示时长
+        this.currentDuration = data.duration || 2.0;
+        
         // 设置Toast文本
         this.setToastMessage(data.message);
         
@@ -73,7 +77,7 @@ export class ToastAni extends Component {
         
         tween(this.node)
             .to(0.5, { position: targetPosition }, { easing: 'sineOut' })
-            .delay(0.3)
+            .delay(this.currentDuration)
             .call(() => {
                 this.playSlideOutAnimation();
             })

+ 25 - 4
assets/scripts/CombatSystem/BulletEffects/BulletHitEffect.ts

@@ -151,7 +151,12 @@ export class BulletHitEffect extends Component {
      * 处理普通伤害
      */
     private processNormalDamage(params: any, hitNode: Node): number {
-        const damage = params.damage || 0;
+        // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
+        const weaponBullet = this.getComponent('WeaponBullet') as any;
+        const damage = weaponBullet ? weaponBullet.getFinalDamage() : (params.damage || 0);
+        
+        console.log(`[BulletHitEffect] 普通伤害处理 - 配置伤害: ${params.damage || 0}, 最终伤害: ${damage}`);
+        
         this.damageEnemy(hitNode, damage);
         this.spawnHitEffect(hitNode.worldPosition);
         return damage;
@@ -161,7 +166,12 @@ export class BulletHitEffect extends Component {
      * 处理穿透伤害
      */
     private processPierceDamage(params: PierceParams, hitNode: Node): number {
-        const damage = params.damage || 0;
+        // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
+        const weaponBullet = this.getComponent('WeaponBullet') as any;
+        const damage = weaponBullet ? weaponBullet.getFinalDamage() : (params.damage || 0);
+        
+        console.log(`[BulletHitEffect] 穿透伤害处理 - 配置伤害: ${params.damage || 0}, 最终伤害: ${damage}`);
+        
         this.damageEnemy(hitNode, damage);
         this.spawnHitEffect(hitNode.worldPosition);
         this.pierceCount++;
@@ -172,12 +182,18 @@ export class BulletHitEffect extends Component {
      * 处理爆炸效果
      */
     private processExplosion(params: ExplosionParams, position: Vec3): number {
+        // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
+        const weaponBullet = this.getComponent('WeaponBullet') as any;
+        const finalDamage = weaponBullet ? weaponBullet.getFinalDamage() : (params.damage || 0);
+        
+        console.log(`[BulletHitEffect] 爆炸伤害处理 - 配置伤害: ${params.damage || 0}, 最终伤害: ${finalDamage}`);
+        
         const scheduleExplosion = () => {
             // 生成爆炸特效
             this.spawnExplosionEffect(position);
             
             // 对范围内敌人造成伤害
-            const damage = this.damageEnemiesInRadius(position, params.radius, params.damage);
+            const damage = this.damageEnemiesInRadius(position, params.radius, finalDamage);
             return damage;
         };
         
@@ -235,7 +251,12 @@ export class BulletHitEffect extends Component {
      * 处理弹射伤害
      */
     private processRicochetDamage(params: RicochetParams, hitNode: Node): number {
-        const damage = params.damage || 0;
+        // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
+        const weaponBullet = this.getComponent('WeaponBullet') as any;
+        const damage = weaponBullet ? weaponBullet.getFinalDamage() : (params.damage || 0);
+        
+        console.log(`[BulletHitEffect] 弹射伤害处理 - 配置伤害: ${params.damage || 0}, 最终伤害: ${damage}`);
+        
         this.damageEnemy(hitNode, damage);
         
         if (this.ricochetCount < params.ricochetCount) {

+ 31 - 11
assets/scripts/CombatSystem/WeaponBullet.ts

@@ -6,6 +6,7 @@ import { BulletLifecycle, BulletLifecycleConfig } from './BulletEffects/BulletLi
 import { ConfigManager } from '../Core/ConfigManager';
 import  EventBus,{ GameEvents } from '../Core/EventBus';
 import { PersistentSkillManager } from '../FourUI/SkillSystem/PersistentSkillManager';
+import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 
 const { ccclass, property } = _decorator;
 
@@ -67,13 +68,14 @@ export class WeaponBullet extends Component {
         WeaponBullet.shootingEnabled = enable;
     }
 
-    // === 子模块组件 ===
+    // 子弹组件
     private bulletTrajectory: BulletTrajectory = null;
     private bulletHitEffect: BulletHitEffect = null;
     private bulletLifecycle: BulletLifecycle = null;
     
-    // === 配置数据 ===
+    // 武器配置和状态
     private weaponConfig: WeaponConfig = null;
+    private weaponId: string = null; // 存储武器ID用于获取升级数据
     private isInitialized: boolean = false;
     
     // === 静态武器配置缓存 ===
@@ -231,6 +233,9 @@ export class WeaponBullet extends Component {
             return;
         }
         
+        // 存储武器ID
+        this.weaponId = initData.weaponId;
+        
         // 获取武器配置
         this.weaponConfig = initData.weaponConfig || WeaponBullet.getWeaponConfig(initData.weaponId);
         if (!this.weaponConfig) {
@@ -639,25 +644,40 @@ export class WeaponBullet extends Component {
     }
     
     /**
-     * 计算运行时数值(应用技能加成)
+     * 计算运行时数值(应用武器升级和技能加成)
      */
     private calculateRuntimeStats() {
+        // 获取基础伤害
+        let baseDamage = this.weaponConfig.stats.damage;
+        
+        // 应用武器升级加成
+        const saveDataManager = SaveDataManager.getInstance();
+        if (saveDataManager && this.weaponId) {
+            const weaponData = saveDataManager.getWeapon(this.weaponId);
+            if (weaponData && weaponData.level > 0) {
+                // 应用武器升级加成:升级后伤害 = 基础伤害 + (等级 - 1)
+                baseDamage = this.weaponConfig.stats.damage + (weaponData.level - 1);
+                console.log(`[WeaponBullet] 武器升级加成应用 - 武器ID: ${this.weaponId}, 等级: ${weaponData.level}, 基础伤害: ${this.weaponConfig.stats.damage}, 升级后伤害: ${baseDamage}`);
+            }
+        }
+        
         const skillManager = PersistentSkillManager.getInstance();
         if (!skillManager) {
-            // 如果没有技能管理器,使用基础数值
+            // 如果没有技能管理器,使用升级后的基础数值
             this.weaponConfig.runtimeStats = {
-                finalDamage: this.weaponConfig.stats.damage,
-                finalCritDamage: this.weaponConfig.stats.damage,
+                finalDamage: baseDamage,
+                finalCritDamage: baseDamage,
                 critChance: 0.1 // 基础暴击率10%
             };
+            console.log(`[WeaponBullet] 无技能管理器 - 最终伤害: ${baseDamage}`);
             return;
         }
         
-        // 应用伤害加成
-        const finalDamage = skillManager.applyDamageBonus(this.weaponConfig.stats.damage);
+        // 应用技能伤害加成(基于升级后的伤害)
+        const finalDamage = skillManager.applyDamageBonus(baseDamage);
         
-        // 应用暴击伤害加成
-        const finalCritDamage = skillManager.applyCritDamageBonus(this.weaponConfig.stats.damage);
+        // 应用技能暴击伤害加成(基于升级后的伤害)
+        const finalCritDamage = skillManager.applyCritDamageBonus(baseDamage);
         
         // 设置基础暴击率为10%
         const critChance = 0.1;
@@ -668,7 +688,7 @@ export class WeaponBullet extends Component {
             critChance
         };
         
-        console.log(`[WeaponBullet] 技能加成计算完成 - 基础伤害: ${this.weaponConfig.stats.damage}, 最终伤害: ${finalDamage}, 暴击伤害: ${finalCritDamage}, 暴击率: ${(critChance * 100).toFixed(1)}%`);
+        console.log(`[WeaponBullet] 完整伤害计算完成 - 武器ID: ${this.weaponId}, 基础伤害: ${this.weaponConfig.stats.damage}, 升级后伤害: ${baseDamage}, 最终伤害: ${finalDamage}, 暴击伤害: ${finalCritDamage}, 暴击率: ${(critChance * 100).toFixed(1)}%`);
     }
     
     /**

+ 1 - 0
assets/scripts/Core/EventBus.ts

@@ -35,6 +35,7 @@ export enum GameEvents {
     // UI事件
     UPGRADE_UPDATED = 'UPGRADE_UPDATED',
     RETURN_TO_MAIN_MENU = 'RETURN_TO_MAIN_MENU',
+    CURRENCY_CHANGED = 'CURRENCY_CHANGED',
     
     // UI状态切换事件(根据游戏管理文档)
     ENTER_BATTLE_PREPARATION = 'ENTER_BATTLE_PREPARATION',  // 进入备战阶段

+ 6 - 4
assets/scripts/FourUI/MainSystem/MainUIControlller.ts

@@ -83,7 +83,8 @@ export class MainUIController extends Component {
     
     // 刷新所有UI显示
     this.refreshAll();
-    TopBarController.updateTopBarUI();
+    // 通过事件系统通知UI更新
+    EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
   }
 
   private onBattle () {
@@ -220,8 +221,8 @@ export class MainUIController extends Component {
   public updateUI (): void {
     this.refreshAll();
     
-    // 同时更新TopBar的UI
-    TopBarController.updateTopBarUI();
+    // 通过事件系统通知UI更新
+    EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
   }
 
   /**
@@ -268,7 +269,8 @@ export class MainUIController extends Component {
 
     // 刷新UI显示
     this.refreshAll();
-    TopBarController.updateTopBarUI();
+    // 通过事件系统通知UI更新
+    EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
     
     console.log('MainUIController.onReturnToMainUI 执行完成');
   }

+ 62 - 15
assets/scripts/FourUI/TopBarController.ts

@@ -1,6 +1,7 @@
 // TopBarController.ts
 import { _decorator, Component, Node, Button, Label, find } from 'cc';
 import { SaveDataManager } from '../LevelSystem/SaveDataManager';
+import EventBus, { GameEvents } from '../Core/EventBus';
 const { ccclass, property } = _decorator;
 
 @ccclass('TopBarController')
@@ -18,6 +19,36 @@ export class TopBarController extends Component {
     this.sdm = SaveDataManager.getInstance();
     this.bindButtons();
     this.refreshAll();
+    // 监听货币变化事件
+    this.setupEventListeners();
+  }
+
+  onDestroy() {
+    // 移除事件监听
+    this.removeEventListeners();
+  }
+
+  /* 设置事件监听 */
+  private setupEventListeners() {
+    const eventBus = EventBus.getInstance();
+    
+    // 监听游戏开始事件,初始显示货币
+    eventBus.on(GameEvents.GAME_START, this.refreshCurrency, this);
+    
+    // 监听货币变化事件
+    eventBus.on(GameEvents.CURRENCY_CHANGED, this.refreshCurrency, this);
+    
+    // 监听UI重置事件
+    eventBus.on(GameEvents.RESET_UI_STATES, this.refreshAll, this);
+  }
+  
+  /* 移除事件监听 */
+  private removeEventListeners() {
+    const eventBus = EventBus.getInstance();
+    
+    eventBus.off(GameEvents.GAME_START, this.refreshCurrency, this);
+    eventBus.off(GameEvents.CURRENCY_CHANGED, this.refreshCurrency, this);
+    eventBus.off(GameEvents.RESET_UI_STATES, this.refreshAll, this);
   }
 
   /* 绑定按钮事件 */
@@ -30,42 +61,58 @@ export class TopBarController extends Component {
 
   /* ================= 业务逻辑 ================= */
   private addCoins(v: number) { 
-    this.sdm.addCoins(v, 'ad'); 
-    this.refreshCurrency(); 
+    this.sdm.addMoney(v, 'ad'); 
+    // 触发货币变化事件
+    EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
   }
   
   private addDiamonds(v: number) { 
     this.sdm.addDiamonds(v, 'ad'); 
-    this.refreshCurrency(); 
+    // 触发货币变化事件
+    EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
   }
 
 
 
   /* ================= 刷新 ================= */
   private refreshCurrency() {
+    // 确保SaveDataManager已初始化
+    if (!this.sdm) {
+      console.warn('[TopBarController] SaveDataManager未初始化,跳过货币刷新');
+      return;
+    }
+    
+    // 如果SaveDataManager还没有调用initialize(),先初始化
+    this.sdm.initialize();
+    
+    const currentCoins = this.sdm.getMoney();
+    const currentDiamonds = this.sdm.getDiamonds();
+    
+    console.log(`[TopBarController] 刷新货币显示 - 金钱: ${currentCoins}, 钻石: ${currentDiamonds}`);
+    
     const mLbl = this.moneyLabel?.getComponent(Label) || this.moneyLabel as unknown as Label;
-    if (mLbl) mLbl.string = this.format(this.sdm.getCoins());
+    if (mLbl) {
+      const formattedCoins = this.format(currentCoins);
+      mLbl.string = formattedCoins;
+      console.log(`[TopBarController] 金钱显示更新为: ${formattedCoins}`);
+    }
+    
     const dLbl = this.diamondLabel?.getComponent(Label) || this.diamondLabel as unknown as Label;
-    if (dLbl) dLbl.string = this.format(this.sdm.getDiamonds());
+    if (dLbl) {
+      const formattedDiamonds = this.format(currentDiamonds);
+      dLbl.string = formattedDiamonds;
+      console.log(`[TopBarController] 钻石显示更新为: ${formattedDiamonds}`);
+    }
   }
   
   private refreshAll() {
     this.refreshCurrency();
   }
 
-  // 供外部调用的公共刷新接口
+  // 供外部调用的公共刷新接口(保留以防其他地方需要手动刷新)
   public updateUI(): void {
     this.refreshAll();
   }
-
-  // 供其他控制器调用的静态更新方法
-  public static updateTopBarUI(): void {
-    const topBarNode = find('Canvas/TopBar');
-    const topBarController = topBarNode?.getComponent('TopBarController');
-    if (topBarController && 'updateUI' in topBarController) {
-      (topBarController as any).updateUI();
-    }
-  }
   
   /* =============== Util =============== */
   private format(n: number) { 

+ 107 - 30
assets/scripts/FourUI/UpgradeSystem/UpgradeController.ts

@@ -1,6 +1,5 @@
 import { _decorator, Component, Node, Button, Label, Sprite, SpriteFrame, Texture2D, resources, ScrollView, Layout, Prefab, instantiate, find, UIOpacity, Color } from 'cc';
 import { SaveDataManager, WeaponData } from '../../LevelSystem/SaveDataManager';
-import { TopBarController } from '../TopBarController';
 import EventBus, { GameEvents } from '../../Core/EventBus';
 import { UpgradeAni } from './UpgradeAni';
 
@@ -387,10 +386,33 @@ export class UpgradeController extends Component {
             this.loadWeaponSprite(weaponSprite, spritePath);
         }
         
-        // 设置武器名称 - Unlock.prefab中的Name节点下的Label
+        // 设置武器名称 - Unlock.prefab中的Name节点下的Label(只显示武器名称)
         const nameLabel = spriteNode.getChildByName('Name')?.getComponent(Label);
         if (nameLabel) {
-            nameLabel.string = `${weaponConfig.name} Lv.${weaponData ? weaponData.level : 0}`;
+            nameLabel.string = weaponConfig.name;
+        }
+        
+        // 设置武器等级 - should_hide_in_hierarchy/Unlock/Sprite/Level/Label节点(显示等级)    
+        const levelNode = spriteNode.getChildByName('Level');
+        console.log(`[PreviewInEditor] 处理武器等级显示: ${weaponConfig.name}, weaponData:`, weaponData);
+        if (levelNode) {         
+            // 先尝试Level节点本身的Label组件
+            let levelLabel = levelNode.getComponent(Label);
+            if (!levelLabel) {
+                // 如果Level节点本身没有Label,尝试查找子节点Label
+                const labelNode = levelNode.getChildByName('Label');
+                if (labelNode) {
+                    levelLabel = labelNode.getComponent(Label);
+                }
+            }
+            if (levelLabel) {
+                const actualLevel = weaponData ? weaponData.level : 0;
+                levelLabel.string = `${actualLevel}`;
+            } else {
+                console.warn(`[PreviewInEditor] 未找到Level Label组件: ${weaponConfig.name}`);
+            }
+        } else {
+            console.warn(`[PreviewInEditor] 未找到Level节点: ${weaponConfig.name}`);
         }
         
         // 设置升级按钮 - Unlock.prefab中的Button节点
@@ -407,14 +429,15 @@ export class UpgradeController extends Component {
             // 设置按钮文本和状态
             const buttonLabel = upgradeButton.node.getChildByName('Label')?.getComponent(Label);
             if (buttonLabel) {
-                const cost = this.saveDataManager.getWeaponUpgradeCost(weaponConfig.id);
                 const maxLevel = 10; // 假设最大等级为10
                 
                 if (weaponData && weaponData.level >= maxLevel) {
                     buttonLabel.string = '已满级';
                     upgradeButton.interactable = false;
                 } else {
-                    buttonLabel.string = `升级 (${cost}金币)`;
+                    // 只显示"升级",不显示费用,费用在升级面板中显示
+                    buttonLabel.string = '升级';
+                    // 武器节点的升级按钮始终可点击(用于打开升级面板)
                     upgradeButton.interactable = true;
                 }
             }
@@ -526,8 +549,20 @@ export class UpgradeController extends Component {
             upgradeBtn.active = true;
         }
         
+        // 恢复透明度
+        let uiOpacity = weaponNode.getComponent(UIOpacity);
+        if (uiOpacity) {
+            uiOpacity.opacity = 255;
+        }
+        
         // 设置为解锁状态
         this.setupUnlockedWeaponNode(weaponNode, weaponConfig, weaponData);
+        
+        // 启用点击事件
+        const button = weaponNode.getComponent(Button);
+        if (button) {
+            button.interactable = true;
+        }
     }
     
    
@@ -607,8 +642,11 @@ export class UpgradeController extends Component {
         // 计算当前伤害(基础伤害 + 等级加成)- Canvas/UpgradeUI/UpgradePanel/NumberBack/CurrentDamage
         const baseDamage = weaponConfig.stats.damage;
         const currentDamage = this.calculateWeaponDamage(baseDamage, weaponData.level);
+        const nextLevelDamage = this.calculateWeaponDamage(baseDamage, weaponData.level + 1);
+        const damageIncrease = nextLevelDamage - currentDamage;
         
         if (this.panelCurrentDamage) {
+            // 只显示当前伤害数值,不显示增量
             this.panelCurrentDamage.string = currentDamage.toString();
         }
         
@@ -620,15 +658,11 @@ export class UpgradeController extends Component {
         
         // 设置升级按钮状态 - Canvas/UpgradeUI/UpgradePanel/UpgradeBtn
         if (this.panelUpgradeBtn) {
-            const canUpgrade = this.saveDataManager.canUpgradeWeapon(this.currentSelectedWeapon);
-            this.panelUpgradeBtn.interactable = canUpgrade;
+            // 始终保持按钮可点击,金币不足的检查在点击时进行
+            // 这样可以确保用户点击时能看到"金币不足"的提示
+            this.panelUpgradeBtn.interactable = true;
             
-            // 检查金币是否足够
-            const playerData = this.saveDataManager.getPlayerData();
-            const cost = this.saveDataManager.getWeaponUpgradeCost(this.currentSelectedWeapon);
-            if (playerData.coins < cost) {
-                console.log(`金币不足进行升级: 需要 ${cost}, 当前 ${playerData.coins}`);
-            }
+            console.log(`[UpgradeController] 升级按钮设置为可交互状态`);
         }
     }
     
@@ -638,9 +672,9 @@ export class UpgradeController extends Component {
     private calculateWeaponDamage(baseDamage: number, level: number): number {
         if (level === 0) return 0; // 未解锁武器伤害为0
         
-        // 每级增加10%基础伤害
-        const damageMultiplier = 1 + (level - 1) * 0.1;
-        return Math.floor(baseDamage * damageMultiplier);
+        // 伤害增加:升级后伤害 = 升级前伤害 + 1(固定 + 1)
+        // 1级武器 = 基础伤害,每升1级增加1点伤害
+        return baseDamage + (level - 1);
     }
     
     /**
@@ -687,12 +721,60 @@ export class UpgradeController extends Component {
      * 升级武器
      */
     private onUpgradeWeapon() {
-        if (!this.currentSelectedWeapon) return;
+        console.log(`[UpgradeController] onUpgradeWeapon方法被调用`);
+        
+        if (!this.currentSelectedWeapon) {
+            console.log(`[UpgradeController] currentSelectedWeapon为空,退出`);
+            return;
+        }
+        
+        console.log(`[UpgradeController] 开始升级武器: ${this.currentSelectedWeapon}`);
+        
+        // 检查升级条件并显示相应提示
+        const weapon = this.saveDataManager.getWeapon(this.currentSelectedWeapon);
+        console.log(`[UpgradeController] 获取到的武器数据:`, weapon);
+        
+        if (!weapon) {
+            console.log(`[UpgradeController] 武器不存在: ${this.currentSelectedWeapon}`);
+            EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "武器不存在", duration: 2.0 });
+            return;
+        }
+        
+        console.log(`[UpgradeController] 武器等级: ${weapon.level}`);
+        if (weapon.level === 0) {
+            console.log(`[UpgradeController] 武器未解锁: ${this.currentSelectedWeapon}`);
+            EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "请先解锁武器", duration: 2.0 });
+            return;
+        }
+        
+        const cost = this.saveDataManager.getWeaponUpgradeCost(this.currentSelectedWeapon);
+        const playerMoney = this.saveDataManager.getMoney();
+        
+        console.log(`[UpgradeController] 升级检查 - 武器: ${this.currentSelectedWeapon}, 费用: ${cost}, 当前金币: ${playerMoney}`);
+        console.log(`[UpgradeController] 费用类型: ${typeof cost}, 金币类型: ${typeof playerMoney}`);
+        console.log(`[UpgradeController] 条件判断: ${playerMoney} < ${cost} = ${playerMoney < cost}`);
+        
+        if (playerMoney < cost) {
+            console.log(`[UpgradeController] 金币不足 - 需要: ${cost}, 当前: ${playerMoney}`);
+            EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: `金币不足,需要${cost}金币`, duration: 2.0 });
+            return;
+        }
+        
+        console.log(`[UpgradeController] 金币充足,继续升级流程`);
+        
+        // 记录升级前的金币数量
+        const coinsBeforeUpgrade = this.saveDataManager.getMoney();
+        console.log(`[UpgradeController] 升级前金币: ${coinsBeforeUpgrade}`);
         
         const success = this.saveDataManager.upgradeWeapon(this.currentSelectedWeapon);
         
         if (success) {
-            console.log(`武器 ${this.currentSelectedWeapon} 升级成功`);
+            const coinsAfterUpgrade = this.saveDataManager.getMoney();
+            console.log(`[UpgradeController] 武器 ${this.currentSelectedWeapon} 升级成功`);
+            console.log(`[UpgradeController] 升级后金币: ${coinsAfterUpgrade}, 消耗: ${coinsBeforeUpgrade - coinsAfterUpgrade}`);
+            
+            // 显示升级成功提示
+            EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "升级成功!", duration: 1.5 });
             
             // 刷新升级面板
             this.refreshUpgradePanel();
@@ -700,13 +782,12 @@ export class UpgradeController extends Component {
             // 使用新的状态切换方法更新武器节点
             this.switchWeaponNodeState(this.currentSelectedWeapon);
             
-            // 更新顶部金币显示
-            TopBarController.updateTopBarUI();
-            
             // 保存数据
             this.saveDataManager.savePlayerData();
         } else {
-            console.log(`武器 ${this.currentSelectedWeapon} 升级失败`);
+            console.log(`[UpgradeController] 武器 ${this.currentSelectedWeapon} 升级失败`);
+            EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "升级失败,请重试", duration: 1.0 });
+            // 升级失败时不更新UI
         }
     }
     
@@ -722,9 +803,6 @@ export class UpgradeController extends Component {
             // 使用新的状态切换方法更新武器节点
             this.switchWeaponNodeState(weaponId);
             
-            // 更新顶部金币显示
-            TopBarController.updateTopBarUI();
-            
             // 保存数据
             this.saveDataManager.savePlayerData();
         }
@@ -767,7 +845,7 @@ export class UpgradeController extends Component {
         console.log(`[UpgradeController] 关卡完成事件触发`);
         console.log(`[UpgradeController] 当前关卡: ${currentLevel}, 最大解锁关卡: ${maxUnlockedLevel}`);
         console.log(`[UpgradeController] 玩家数据:`, {
-            coins: playerData?.coins || 0,
+            coins: playerData?.money || 0,
             currentLevel: playerData?.currentLevel || 1,
             maxUnlockedLevel: playerData?.maxUnlockedLevel || 1
         });
@@ -848,9 +926,8 @@ export class UpgradeController extends Component {
         return {
             currentLevel: this.saveDataManager.getCurrentLevel(),
             maxUnlockedLevel: this.saveDataManager.getMaxUnlockedLevel(),
-            coins: this.saveDataManager.getCoins(),
-            diamonds: this.saveDataManager.getDiamonds(),
-            gems: this.saveDataManager.getGems(),
+            coins: this.saveDataManager.getMoney(),
+                diamonds: this.saveDataManager.getDiamonds(),
             wallLevel: this.saveDataManager.getWallLevel()
         };
     }
@@ -969,7 +1046,7 @@ export class UpgradeController extends Component {
         
         console.log(`当前关卡: ${currentLevel}`);
         console.log(`最大解锁关卡: ${maxUnlockedLevel}`);
-        console.log(`金币: ${playerData?.coins || 0}`);
+        console.log(`金钱: ${playerData?.money || 0}`);
         
         console.log('\n=== 关卡完成状态 ===');
         for (let i = 1; i <= 5; i++) {

+ 1 - 2
assets/scripts/LevelSystem/GameManager.ts

@@ -922,9 +922,8 @@ export class GameManager extends Component {
             data: levelData,
             config: levelConfig,
             playerData: this.saveDataManager ? {
-                coins: this.saveDataManager.getCoins(),
+                coins: this.saveDataManager.getMoney(),
                 diamonds: this.saveDataManager.getDiamonds(),
-                gems: this.saveDataManager.getGems(),
                 wallLevel: this.saveDataManager.getWallLevel()
             } : null
         };

+ 5 - 8
assets/scripts/LevelSystem/README_SaveSystem.md

@@ -46,13 +46,13 @@ saveManager.initialize();
 // 获取墙体等级
 const wallLevel = saveManager.getWallLevel();
 const currentLevel = saveManager.getCurrentLevel();
-const coins = saveManager.getCoins();
+const coins = saveManager.getMoney();
 
 // 完成关卡
 saveManager.completeLevel(levelId, score, time, stars);
 
 // 添加货币
-saveManager.addCoins(amount, 'level_complete');
+saveManager.addMoney(amount, 'level_complete');
 saveManager.addDiamonds(amount, 'daily_reward');
 ```
 
@@ -103,7 +103,7 @@ export class MainUIController extends Component {
         this.wallLevelLabel.string = `墙体等级: ${wallLevel}`;
         
         // 更新货币显示
-        const coins = this.saveDataManager.getCoins();
+        const coins = this.saveDataManager.getMoney();
         this.coinsLabel.string = coins.toString();
     }
 }
@@ -127,7 +127,6 @@ interface PlayerData {
     // 货币系统
     coins: number;
     diamonds: number;
-    gems: number;
     
     // 关卡进度
     currentLevel: number;
@@ -167,7 +166,6 @@ interface LevelProgress {
 - `getMaxUnlockedLevel()`: 获取最高解锁关卡
 - `getCoins()`: 获取金币数量
 - `getDiamonds()`: 获取钻石数量
-- `getGems()`: 获取宝石数量
 
 ### 关卡管理
 - `completeLevel(levelId, score, time)`: 完成关卡
@@ -181,7 +179,6 @@ interface LevelProgress {
 - `spendCoins(amount)`: 消费金币
 - `addDiamonds(amount, source)`: 添加钻石
 - `spendDiamonds(amount)`: 消费钻石
-- `addGems(amount, source)`: 添加宝石
 
 ### 墙体等级管理
 - `upgradeWallLevel()`: 升级墙体等级
@@ -219,7 +216,7 @@ saveManager.initialize();
 // 显示玩家信息
 const wallLevel = saveManager.getWallLevel();
 const currentLevel = saveManager.getCurrentLevel();
-const coins = saveManager.getCoins();
+const coins = saveManager.getMoney();
 ```
 
 ### 3. 进入关卡
@@ -244,7 +241,7 @@ const time = getGameDuration();
 saveManager.completeLevel(currentLevel, score, time);
 
 // 给予奖励
-saveManager.addCoins(baseReward, 'level_complete');
+saveManager.addMoney(baseReward, 'level_complete');
 ```
 
 ### 6. 关卡失败

+ 89 - 67
assets/scripts/LevelSystem/SaveDataManager.ts

@@ -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}`;
     }