Jelajahi Sumber

关卡优化

181404010226 4 bulan lalu
induk
melakukan
84c2484f42
34 mengubah file dengan 2742 tambahan dan 4054 penghapusan
  1. 476 3827
      assets/Scenes/GameLevel.scene
  2. 1 1
      assets/resources/data/ballController.json
  3. 1 1
      assets/resources/data/excel/config_manager.py
  4. TEMPAT SAMPAH
      assets/resources/data/excel/关卡配置/关卡配置表.xlsx
  5. 1 1
      assets/resources/data/levels/Level2.json
  6. 1 1
      assets/resources/data/levels/Level3.json
  7. 1 1
      assets/resources/data/levels/Level4.json
  8. 1 1
      assets/resources/data/levels/Level5.json
  9. 1 1
      assets/resources/data/levels/Level6.json
  10. 1 1
      assets/resources/data/levels/Level7.json
  11. 1 1
      assets/resources/data/levels/Level8.json
  12. 1 1
      assets/resources/data/levels/Level9.json
  13. 72 48
      assets/resources/data/skill.json
  14. 1689 0
      assets/resources/prefabs/Skill1.prefab
  15. 13 0
      assets/resources/prefabs/Skill1.prefab.meta
  16. 16 16
      assets/scripts/Animations/MoneyAni.ts
  17. 0 3
      assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts
  18. 11 0
      assets/scripts/CombatSystem/EnemyController.ts
  19. 2 2
      assets/scripts/CombatSystem/GameEnd.ts
  20. 6 23
      assets/scripts/CombatSystem/SkillSelection/SkillButtonAnimator.ts
  21. 216 0
      assets/scripts/CombatSystem/SkillSelection/SkillButtonController.ts
  22. 9 0
      assets/scripts/CombatSystem/SkillSelection/SkillButtonController.ts.meta
  23. 96 10
      assets/scripts/CombatSystem/SkillSelection/SkillManager.ts
  24. 29 76
      assets/scripts/CombatSystem/SkillSelection/SkillSelectionController.ts
  25. 1 1
      assets/scripts/CombatSystem/Wall.ts
  26. 1 1
      assets/scripts/CombatSystem/WeaponBullet.ts
  27. 0 7
      assets/scripts/Core/ConfigManager.ts
  28. 7 7
      assets/scripts/FourUI/MainSystem/MainUIControlller.ts
  29. 5 5
      assets/scripts/FourUI/TopBarController.ts
  30. 6 6
      assets/scripts/FourUI/UpgradeSystem/UpgradeController.ts
  31. 2 2
      assets/scripts/LevelSystem/GameManager.ts
  32. 1 1
      assets/scripts/LevelSystem/IN_game.ts
  33. 9 9
      assets/scripts/LevelSystem/SaveDataManager.ts
  34. 65 0
      test_skill_system.js

File diff ditekan karena terlalu besar
+ 476 - 3827
assets/Scenes/GameLevel.scene


+ 1 - 1
assets/resources/data/ballController.json

@@ -1,5 +1,5 @@
 {
-  "baseSpeed": 12.0,
+  "baseSpeed": 32.0,
   "maxReflectionRandomness": 0.2,
   "antiTrapTimeWindow": 5,
   "antiTrapHitThreshold": 5,

+ 1 - 1
assets/resources/data/excel/config_manager.py

@@ -1013,7 +1013,7 @@ class ConfigManagerGUI:
                     'diamondReward': int(basic_row['钻石奖励']) if pd.notna(basic_row['钻石奖励']) else 0,
                     'timeLimit': 300,  # 默认值
                     'difficulty': 'normal',  # 默认值
-                    'healthMultiplier': 1.0,  # 默认值
+                    'healthMultiplier': float(basic_row['生命倍数']) if pd.notna(basic_row['生命倍数']) else 1.0,  # 从Excel读取生命倍数
                     'waves': []
                 }
                 

TEMPAT SAMPAH
assets/resources/data/excel/关卡配置/关卡配置表.xlsx


+ 1 - 1
assets/resources/data/levels/Level2.json

@@ -11,7 +11,7 @@
   "diamondReward": 30,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 1.2,
   "waves": [
     {
       "waveId": 1,

+ 1 - 1
assets/resources/data/levels/Level3.json

@@ -12,7 +12,7 @@
   "diamondReward": 50,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 1.4,
   "waves": [
     {
       "waveId": 1,

+ 1 - 1
assets/resources/data/levels/Level4.json

@@ -13,7 +13,7 @@
   "diamondReward": 80,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 1.6,
   "waves": [
     {
       "waveId": 1,

+ 1 - 1
assets/resources/data/levels/Level5.json

@@ -14,7 +14,7 @@
   "diamondReward": 100,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 1.8,
   "waves": [
     {
       "waveId": 1,

+ 1 - 1
assets/resources/data/levels/Level6.json

@@ -15,7 +15,7 @@
   "diamondReward": 120,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 2.0,
   "waves": [
     {
       "waveId": 1,

+ 1 - 1
assets/resources/data/levels/Level7.json

@@ -16,7 +16,7 @@
   "diamondReward": 150,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 2.2,
   "waves": [
     {
       "waveId": 1,

+ 1 - 1
assets/resources/data/levels/Level8.json

@@ -17,7 +17,7 @@
   "diamondReward": 170,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 2.4,
   "waves": [
     {
       "waveId": 1,

+ 1 - 1
assets/resources/data/levels/Level9.json

@@ -18,7 +18,7 @@
   "diamondReward": 200,
   "timeLimit": 300,
   "difficulty": "normal",
-  "healthMultiplier": 1.0,
+  "healthMultiplier": 2.6,
   "waves": [
     {
       "waveId": 1,

+ 72 - 48
assets/resources/data/skill.json

@@ -3,92 +3,116 @@
     {
       "id": "cheaper_units",
       "name": "花费降低",
-      "description": "购买植物价格降低10%。",
+      "description": "购买植物价格降低{value}%。",
       "iconPath": "images/SkillImages/cheaper_units",
       "maxLevel": 5,
       "currentLevel": 0,
-      "priceReduction": 0.1,
-      "critChanceIncrease": 0.0,
-      "critDamageBonus": 0.0,
-      "healthIncrease": 0.0,
-      "multiShotChance": 0.0,
-      "energyGainIncrease": 0.0,
-      "ballSpeedIncrease": 0.0
+      "levelEffects": {
+        "priceReduction": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
+        "descriptions": [
+          "购买植物价格降低10%。",
+          "购买植物价格降低20%。",
+          "购买植物价格降低30%。",
+          "购买植物价格降低40%。",
+          "购买植物价格降低50%。",
+          "购买植物价格降低60%。"
+        ]
+      }
     },
     {
       "id": "crit_chance",
       "name": "暴击几率",
-      "description": "造成暴击伤害几率提高10%",
+      "description": "造成暴击伤害几率提高{value}%",
       "iconPath": "images/SkillImages/crit_chance",
       "maxLevel": 5,
       "currentLevel": 0,
-      "priceReduction": 0.0,
-      "critChanceIncrease": 0.1,
-      "critDamageBonus": 0.0,
-      "healthIncrease": 0.0,
-      "multiShotChance": 0.0,
-      "energyGainIncrease": 0.0,
-      "ballSpeedIncrease": 0.0
+      "levelEffects": {
+        "critChanceIncrease":  [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
+        "descriptions": [
+          "造成暴击伤害几率提高10%。",
+          "造成暴击伤害几率提高20%。",
+          "造成暴击伤害几率提高30%。",
+          "造成暴击伤害几率提高40%。",
+          "造成暴击伤害几率提高50%。",
+          "造成暴击伤害几率提高60%。"
+        ]
+      }
     },
     {
       "id": "heal",
       "name": "增加生命",
-      "description": "生命值增加10%。",
+      "description": "生命值增加{value}%。",
       "iconPath": "images/SkillImages/heal",
       "maxLevel": 5,
       "currentLevel": 0,
-      "priceReduction": 0.0,
-      "critChanceIncrease": 0.0,
-      "critDamageBonus": 0.0,
-      "healthIncrease": 0.1,
-      "multiShotChance": 0.0,
-      "energyGainIncrease": 0.0,
-      "ballSpeedIncrease": 0.0
+      "levelEffects": {
+        "healthIncrease":  [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
+        "descriptions": [
+          "生命值增加10%。",
+          "生命值增加20%。",
+          "生命值增加30%。",
+          "生命值增加40%。",
+          "生命值增加50%。",
+          "生命值增加60%。"
+        ]
+      }
     },
     {
       "id": "multi_shots",
       "name": "多重射击",
-      "description": "攻击有10%的几率射出两发子弹",
+      "description": "攻击有{value}%的几率射出两发子弹",
       "iconPath": "images/SkillImages/multi_shots",
       "maxLevel": 5,
       "currentLevel": 0,
-      "priceReduction": 0.0,
-      "critChanceIncrease": 0.0,
-      "critDamageBonus": 0.0,
-      "healthIncrease": 0.0,
-      "multiShotChance": 0.1,
-      "energyGainIncrease": 0.0,
-      "ballSpeedIncrease": 0.0
+      "levelEffects": {
+        "multiShotChance":  [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
+        "descriptions": [
+          "攻击有10%的几率射出两发子弹。",
+          "攻击有20%的几率射出两发子弹。",
+          "攻击有30%的几率射出两发子弹。",
+          "攻击有40%的几率射出两发子弹。",
+          "攻击有50%的几率射出两发子弹。",
+          "攻击有60%的几率射出两发子弹。"
+        ]
+      }
     },
     {
       "id": "energy_hunter",
       "name": "能量猎手",
-      "description": "获取的能量值增加10%。",
+      "description": "获取的能量值增加{value}%。",
       "iconPath": "images/SkillImages/xp_hunter",
       "maxLevel": 5,
       "currentLevel": 0,
-      "priceReduction": 0.0,
-      "critChanceIncrease": 0.0,
-      "critDamageBonus": 0.0,
-      "healthIncrease": 0.0,
-      "multiShotChance": 0.0,
-      "energyGainIncrease": 0.1,
-      "ballSpeedIncrease": 0.0
+      "levelEffects": {
+        "energyGainIncrease":  [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
+        "descriptions": [
+          "获取的能量值增加10%。",
+          "获取的能量值增加20%。",
+          "获取的能量值增加30%。",
+          "获取的能量值增加40%。",
+          "获取的能量值增加50%。",
+          "获取的能量值增加60%。"
+        ]
+      }
     },
     {
       "id": "ball_speed",
       "name": "球速提升",
-      "description": "球的飞行速度加快10%。",
+      "description": "球的飞行速度加快{value}%。",
       "iconPath": "images/SkillImages/ball_speed",
       "maxLevel": 5,
       "currentLevel": 0,
-      "priceReduction": 0.0,
-      "critChanceIncrease": 0.0,
-      "critDamageBonus": 0.0,
-      "healthIncrease": 0.0,
-      "multiShotChance": 0.0,
-      "energyGainIncrease": 0.0,
-      "ballSpeedIncrease": 0.1
+      "levelEffects": {
+        "ballSpeedIncrease":  [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
+        "descriptions": [
+          "球的飞行速度加快10%。",
+          "球的飞行速度加快20%。",
+          "球的飞行速度加快30%。",
+          "球的飞行速度加快40%。",
+          "球的飞行速度加快50%。",
+          "球的飞行速度加快60%。"
+        ]
+      }
     }
   ]
 }

+ 1689 - 0
assets/resources/prefabs/Skill1.prefab

@@ -0,0 +1,1689 @@
+[
+  {
+    "__type__": "cc.Prefab",
+    "_name": "Skill1",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_native": "",
+    "data": {
+      "__id__": 1
+    },
+    "optimizationPolicy": 0,
+    "persistent": false
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "Skill1",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": null,
+    "_children": [
+      {
+        "__id__": 2
+      },
+      {
+        "__id__": 46
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 60
+      },
+      {
+        "__id__": 62
+      },
+      {
+        "__id__": 64
+      },
+      {
+        "__id__": 66
+      },
+      {
+        "__id__": 68
+      },
+      {
+        "__id__": 70
+      }
+    ],
+    "_prefab": {
+      "__id__": 72
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 270,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 1,
+      "y": 1,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "SkillSprite",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [
+      {
+        "__id__": 3
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 41
+      },
+      {
+        "__id__": 43
+      }
+    ],
+    "_prefab": {
+      "__id__": 45
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": -182.0687255859375,
+      "y": 24.878,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 1,
+      "y": 1,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "Star",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 2
+    },
+    "_children": [
+      {
+        "__id__": 4
+      },
+      {
+        "__id__": 10
+      },
+      {
+        "__id__": 16
+      },
+      {
+        "__id__": 22
+      },
+      {
+        "__id__": 28
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 34
+      },
+      {
+        "__id__": 36
+      },
+      {
+        "__id__": 38
+      }
+    ],
+    "_prefab": {
+      "__id__": 40
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 3.6499999999999986,
+      "y": -83.71000000000001,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 1,
+      "y": 1,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "xx-1",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 3
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 5
+      },
+      {
+        "__id__": 7
+      }
+    ],
+    "_prefab": {
+      "__id__": 9
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": -28.5,
+      "y": 0,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 0.2,
+      "y": 0.2,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 4
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 6
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 43,
+      "height": 60
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "e7eaOk6SJBv4McIhwbYaYF"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 4
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 8
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_spriteFrame": {
+      "__uuid__": "8b8af6dd-5729-43f2-9010-d397f216f9cc@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 1,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "07OeYsogRHNIXUVopIYlCS"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "8ayXJw0HZJa5pY+FYASv7d",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "xx-2",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 3
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 11
+      },
+      {
+        "__id__": 13
+      }
+    ],
+    "_prefab": {
+      "__id__": 15
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": -5.5,
+      "y": 0,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 0.2,
+      "y": 0.2,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 10
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 12
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 43,
+      "height": 60
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "0cRcr+whtAVrN+xiYu/U5H"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 10
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 14
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 58,
+      "g": 37,
+      "b": 37,
+      "a": 255
+    },
+    "_spriteFrame": {
+      "__uuid__": "8b8af6dd-5729-43f2-9010-d397f216f9cc@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 1,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "83IhATerRBlr2c9G5wplF5"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "32XzrHbqFFg584HRselCe+",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "xx-3",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 3
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 17
+      },
+      {
+        "__id__": 19
+      }
+    ],
+    "_prefab": {
+      "__id__": 21
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 17.5,
+      "y": 0,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 0.2,
+      "y": 0.2,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 16
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 18
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 43,
+      "height": 60
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "e5cnD4o1VCEqiUa4S6axcu"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 16
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 20
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 58,
+      "g": 37,
+      "b": 37,
+      "a": 255
+    },
+    "_spriteFrame": {
+      "__uuid__": "8b8af6dd-5729-43f2-9010-d397f216f9cc@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 1,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "a5D56ukj9IZYY37anumqI1"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "5eVY0TSr5NnLPMWQ8O/uFa",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "xx-4",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 3
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 23
+      },
+      {
+        "__id__": 25
+      }
+    ],
+    "_prefab": {
+      "__id__": 27
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 40.5,
+      "y": 0,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 0.2,
+      "y": 0.2,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 22
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 24
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 43,
+      "height": 60
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "6bDglIg5RBpqWhwX0OfeGe"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 22
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 26
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 58,
+      "g": 37,
+      "b": 37,
+      "a": 255
+    },
+    "_spriteFrame": {
+      "__uuid__": "8b8af6dd-5729-43f2-9010-d397f216f9cc@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 1,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "926oP1e65H0qeT8u0Y4Jj0"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "e6+vkcuvtE+Knqn/YQmcq1",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "xx-5",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 3
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 29
+      },
+      {
+        "__id__": 31
+      }
+    ],
+    "_prefab": {
+      "__id__": 33
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 63.5,
+      "y": 0,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 0.2,
+      "y": 0.2,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 28
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 30
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 43,
+      "height": 60
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "4fY6wwUz5HmaGMiLdef5U2"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 28
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 32
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 58,
+      "g": 37,
+      "b": 37,
+      "a": 255
+    },
+    "_spriteFrame": {
+      "__uuid__": "8b8af6dd-5729-43f2-9010-d397f216f9cc@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 1,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "dfCpCys39C5I7fa/n5k+id"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "f5m/O92gRJVox3zWLGDi8a",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 3
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 35
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 100,
+      "height": 50
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "1eoPVVnV9Ks73YhyFyhvJN"
+  },
+  {
+    "__type__": "cc.Layout",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 3
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 37
+    },
+    "_resizeMode": 0,
+    "_layoutType": 1,
+    "_cellSize": {
+      "__type__": "cc.Size",
+      "width": 40,
+      "height": 40
+    },
+    "_startAxis": 0,
+    "_paddingLeft": 0,
+    "_paddingRight": 0,
+    "_paddingTop": 0,
+    "_paddingBottom": 0,
+    "_spacingX": -20,
+    "_spacingY": 0,
+    "_verticalDirection": 1,
+    "_horizontalDirection": 0,
+    "_constraint": 0,
+    "_constraintNum": 2,
+    "_affectedByScale": false,
+    "_isAlign": true,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "25xdUajaZBd6XZNh7JhYHW"
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 3
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 39
+    },
+    "_alignFlags": 9,
+    "_target": null,
+    "_left": 0.05,
+    "_right": 0,
+    "_top": 1.07,
+    "_bottom": 0,
+    "_horizontalCenter": 0,
+    "_verticalCenter": 0,
+    "_isAbsLeft": false,
+    "_isAbsRight": true,
+    "_isAbsTop": false,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 0,
+    "_originalHeight": 0,
+    "_alignMode": 2,
+    "_lockFlags": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "71PzIaW79Koah26jumOr0y"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "beb38cRnBCqYftWRQiGrnO",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 42
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 103,
+      "height": 103
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "ecCg0sGDVCHrG65A63cELI"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 44
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_spriteFrame": {
+      "__uuid__": "6f8300a1-ec5f-4726-a4c7-fde21e7fca67@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "b5KGb+WOZCsYh8MxZH8vHB"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "b1LOf7+3xEE5T1fQBhgksG",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "SkillName",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [
+      {
+        "__id__": 47
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 55
+      },
+      {
+        "__id__": 57
+      }
+    ],
+    "_prefab": {
+      "__id__": 59
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 51.3104248046875,
+      "y": 53.642,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 1,
+      "y": 1,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "SkillIntroduce",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 46
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 48
+      },
+      {
+        "__id__": 50
+      },
+      {
+        "__id__": 52
+      }
+    ],
+    "_prefab": {
+      "__id__": 54
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 5.001000000000001,
+      "y": -62.2,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 1,
+      "y": 1,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 1073741824,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 47
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 49
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 350,
+      "height": 70
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "a9nUx3vnNMobC7Iq7TbeTT"
+  },
+  {
+    "__type__": "cc.Label",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 47
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 51
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 240,
+      "g": 194,
+      "b": 13,
+      "a": 255
+    },
+    "_string": "label",
+    "_horizontalAlign": 1,
+    "_verticalAlign": 1,
+    "_actualFontSize": 26,
+    "_fontSize": 25,
+    "_fontFamily": "Arial",
+    "_lineHeight": 40,
+    "_overflow": 2,
+    "_enableWrapText": true,
+    "_font": null,
+    "_isSystemFontUsed": true,
+    "_spacingX": 0,
+    "_isItalic": false,
+    "_isBold": true,
+    "_isUnderline": false,
+    "_underlineHeight": 2,
+    "_cacheMode": 0,
+    "_enableOutline": true,
+    "_outlineColor": {
+      "__type__": "cc.Color",
+      "r": 0,
+      "g": 0,
+      "b": 0,
+      "a": 255
+    },
+    "_outlineWidth": 2,
+    "_enableShadow": false,
+    "_shadowColor": {
+      "__type__": "cc.Color",
+      "r": 0,
+      "g": 0,
+      "b": 0,
+      "a": 255
+    },
+    "_shadowOffset": {
+      "__type__": "cc.Vec2",
+      "x": 2,
+      "y": 2
+    },
+    "_shadowBlur": 2,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "cerLBQQCVDobpT5NSQhj7j"
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 47
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 53
+    },
+    "_alignFlags": 17,
+    "_target": null,
+    "_left": 0,
+    "_right": 0,
+    "_top": 1,
+    "_bottom": 0,
+    "_horizontalCenter": 0.059707514996764556,
+    "_verticalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": false,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": false,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 0,
+    "_originalHeight": 0,
+    "_alignMode": 2,
+    "_lockFlags": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "aaB9L3+AVNMbSyWnFvrBmD"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "60GN0vQthLy5dQxsyTmIk7",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 46
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 56
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 83.75830078125,
+      "height": 54.4
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "dexJvADbNJq5nToNBz3d+O"
+  },
+  {
+    "__type__": "cc.Label",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 46
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 58
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_string": "label",
+    "_horizontalAlign": 1,
+    "_verticalAlign": 1,
+    "_actualFontSize": 35,
+    "_fontSize": 35,
+    "_fontFamily": "Arial",
+    "_lineHeight": 40,
+    "_overflow": 0,
+    "_enableWrapText": true,
+    "_font": null,
+    "_isSystemFontUsed": true,
+    "_spacingX": 0,
+    "_isItalic": false,
+    "_isBold": true,
+    "_isUnderline": false,
+    "_underlineHeight": 2,
+    "_cacheMode": 0,
+    "_enableOutline": true,
+    "_outlineColor": {
+      "__type__": "cc.Color",
+      "r": 0,
+      "g": 0,
+      "b": 0,
+      "a": 255
+    },
+    "_outlineWidth": 2,
+    "_enableShadow": false,
+    "_shadowColor": {
+      "__type__": "cc.Color",
+      "r": 0,
+      "g": 0,
+      "b": 0,
+      "a": 255
+    },
+    "_shadowOffset": {
+      "__type__": "cc.Vec2",
+      "x": 2,
+      "y": 2
+    },
+    "_shadowBlur": 2,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "63cmdXEyVIqKE45bCzX0n2"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "7bqm3NFeRInbszk2MxpQ+Y",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 61
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 527.137451171875,
+      "height": 220
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "78dSmsnKxIm57lWXVyGusP"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 63
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_spriteFrame": {
+      "__uuid__": "6321ae58-7604-481f-b23c-869428971b1f@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "78ozzkVY1D1rjf/Q8oaHuD"
+  },
+  {
+    "__type__": "cc.Button",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 65
+    },
+    "clickEvents": [],
+    "_interactable": true,
+    "_transition": 0,
+    "_normalColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_hoverColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "_pressedColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_disabledColor": {
+      "__type__": "cc.Color",
+      "r": 124,
+      "g": 124,
+      "b": 124,
+      "a": 255
+    },
+    "_normalSprite": null,
+    "_hoverSprite": null,
+    "_pressedSprite": null,
+    "_disabledSprite": null,
+    "_duration": 0.1,
+    "_zoomScale": 1.2,
+    "_target": {
+      "__id__": 1
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "7aBnIolh1JILl+3lPWLSy0"
+  },
+  {
+    "__type__": "cc.Layout",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 67
+    },
+    "_resizeMode": 0,
+    "_layoutType": 1,
+    "_cellSize": {
+      "__type__": "cc.Size",
+      "width": 40,
+      "height": 40
+    },
+    "_startAxis": 0,
+    "_paddingLeft": 30,
+    "_paddingRight": 0,
+    "_paddingTop": 0,
+    "_paddingBottom": 0,
+    "_spacingX": 140,
+    "_spacingY": 0,
+    "_verticalDirection": 1,
+    "_horizontalDirection": 0,
+    "_constraint": 0,
+    "_constraintNum": 2,
+    "_affectedByScale": false,
+    "_isAlign": false,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "62vKgR8dNI7KBv2YMNJOO8"
+  },
+  {
+    "__type__": "66ff2iALrxGqIs2L1IPGc9s",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 69
+    },
+    "skillSpriteNode": {
+      "__id__": 2
+    },
+    "skillNameNode": {
+      "__id__": 46
+    },
+    "skillIntroduceNode": {
+      "__id__": 47
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "9bckw8VnJAVJfh+LK/5rLp"
+  },
+  {
+    "__type__": "8cc2bsQiItIybmuoZ/lHqXP",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 71
+    },
+    "starNodes": [
+      {
+        "__id__": 4
+      },
+      {
+        "__id__": 10
+      },
+      {
+        "__id__": 16
+      },
+      {
+        "__id__": 22
+      },
+      {
+        "__id__": 28
+      }
+    ],
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "98JX+UE8hMgZCfy6AKbrsO"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "83nLR6HrFB4JtBHYcmNcdD",
+    "instance": null,
+    "targetOverrides": null
+  }
+]

+ 13 - 0
assets/resources/prefabs/Skill1.prefab.meta

@@ -0,0 +1,13 @@
+{
+  "ver": "1.1.50",
+  "importer": "prefab",
+  "imported": true,
+  "uuid": "7d75fea5-fd34-4f94-ab87-27803536c5ab",
+  "files": [
+    ".json"
+  ],
+  "subMetas": {},
+  "userData": {
+    "syncNodeName": "Skill1"
+  }
+}

+ 16 - 16
assets/scripts/Animations/MoneyAni.ts

@@ -6,14 +6,14 @@ const { ccclass, property } = _decorator;
 
 /**
  * 奖励动画系统
- * 负责在关卡结束后播放金币和钻石的奖励动画
+ * 负责在关卡结束后播放钞票和钻石的奖励动画
  */
 @ccclass('MoneyAni')
 export class MoneyAni extends Component {
     
     @property({
         type: Prefab,
-        tooltip: '金币预制体'
+        tooltip: '钞票预制体'
     })
     public coinPrefab: Prefab = null;
     
@@ -37,7 +37,7 @@ export class MoneyAni extends Component {
     
     @property({
         type: Node,
-        tooltip: '金币目标节点(TopBar中的金币标签)'
+        tooltip: '钞票目标节点(TopBar中的钞票标签)'
     })
     public coinTargetNode: Node = null;
     
@@ -71,12 +71,12 @@ export class MoneyAni extends Component {
     
     /**
      * 播放奖励动画
-     * @param coinAmount 金币数量
+     * @param coinAmount 钞票数量
      * @param diamondAmount 钻石数量
      * @param onComplete 动画完成回调
      */
     public playRewardAnimation(coinAmount: number, diamondAmount: number, onComplete?: () => void) {
-        console.log(`[MoneyAni] 开始播放奖励动画 - 金币: ${coinAmount}, 钻石: ${diamondAmount}`);
+        console.log(`[MoneyAni] 开始播放奖励动画 - 钞票: ${coinAmount}, 钻石: ${diamondAmount}`);
         
         if (!this.canvasNode) {
             console.error('[MoneyAni] Canvas节点未设置,请在编辑器中拖拽Canvas节点到canvasNode属性');
@@ -95,7 +95,7 @@ export class MoneyAni extends Component {
             }
         };
         
-        // 播放金币动画
+        // 播放钞票动画
         if (coinAmount > 0) {
             this.playCoinAnimation(coinAmount, onAnimationComplete);
         }
@@ -114,29 +114,29 @@ export class MoneyAni extends Component {
     }
     
     /**
-     * 播放金币动画
+     * 播放钞票动画
      */
     private playCoinAnimation(amount: number, onComplete?: () => void) {
         if (!this.coinPrefab) {
-            console.error('[MoneyAni] 金币预制体未设置');
+            console.error('[MoneyAni] 钞票预制体未设置');
             if (onComplete) onComplete();
             return;
         }
         
-        // 使用装饰器引用的金币目标节点
+        // 使用装饰器引用的钞票目标节点
         if (!this.coinTargetNode) {
-            console.error('[MoneyAni] 金币目标节点未设置,请在编辑器中拖拽TopBar中的金币标签节点');
+            console.error('[MoneyAni] 钞票目标节点未设置,请在编辑器中拖拽TopBar中的钞票标签节点');
             if (onComplete) onComplete();
             return;
         }
         
         const targetNode = this.coinTargetNode;
         
-        // 生成金币数量(最多10个,超过则按比例显示)
+        // 生成钞票数量(最多10个,超过则按比例显示)
         const coinCount = Math.min(amount, 10);
         const startPos = this.getRewardStartPosition();
         
-        console.log(`[MoneyAni] 生成${coinCount}个金币动画`);
+        console.log(`[MoneyAni] 生成${coinCount}个钞票动画`);
         
         let coinsCompleted = 0;
         
@@ -146,7 +146,7 @@ export class MoneyAni extends Component {
                 this.createAndAnimateCoin(startPos, targetNode, () => {
                     coinsCompleted++;
                     if (coinsCompleted >= coinCount) {
-                        // 所有金币动画完成,更新数据
+                        // 所有钞票动画完成,更新数据
                         this.saveDataManager.addMoney(amount, 'level_reward');
                         // 通过事件系统通知UI更新
             EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
@@ -202,7 +202,7 @@ export class MoneyAni extends Component {
     }
     
     /**
-     * 创建并播放单个金币动画
+     * 创建并播放单个钞票动画
      */
     private createAndAnimateCoin(startPos: Vec3, targetNode: Node, onComplete?: () => void) {
         const coinNode = instantiate(this.coinPrefab);
@@ -315,7 +315,7 @@ export class MoneyAni extends Component {
     /**
      * 静态方法:播放奖励动画(需要传入实例)
      * @param moneyAniInstance MoneyAni组件实例
-     * @param coinAmount 金币数量
+     * @param coinAmount 钞票数量
      * @param diamondAmount 钻石数量
      * @param onComplete 完成回调
      */
@@ -332,7 +332,7 @@ export class MoneyAni extends Component {
     /**
      * 静态方法:播放奖励动画(简化版本)
      * 自动查找场景中的MoneyAni组件
-     * @param coinAmount 金币数量
+     * @param coinAmount 钞票数量
      * @param diamondAmount 钻石数量
      * @param onComplete 完成回调
      */

+ 0 - 3
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts

@@ -336,9 +336,6 @@ export class GameBlockSelection extends Component {
         
         // 更新显示
         this.updateCoinDisplay();
-        
-        // 可以在这里添加播放奖励动画的逻辑
-        // MoneyAni.playReward(coinsToAdd, 0);
     }
 
     // 刷新方块按钮点击

+ 11 - 0
assets/scripts/CombatSystem/EnemyController.ts

@@ -989,8 +989,19 @@ export class EnemyController extends BaseSingleton {
         // 移除EnemyController内部的击杀计数重置,统一由GameManager管理
         // this.currentWaveEnemiesKilled = 0;
         
+        // 修复问题1:根据波次配置设置生成间隔
+        if (this.currentWaveEnemyConfigs.length > 0) {
+            // 使用第一个敌人配置的spawnInterval,如果有多个配置可以取平均值或最小值
+            const firstEnemyConfig = this.currentWaveEnemyConfigs[0];
+            if (firstEnemyConfig && typeof firstEnemyConfig.spawnInterval === 'number') {
+                this.spawnInterval = firstEnemyConfig.spawnInterval;
+                console.log(`[EnemyController] 设置生成间隔为: ${this.spawnInterval}`);
+            }
+        }
+        
         console.log(`[EnemyController] 开始波次 ${waveNum}/${totalWaves},需要生成 ${totalEnemies} 个敌人`);
         console.log(`[EnemyController] 波次敌人配置:`, this.currentWaveEnemyConfigs);
+        console.log(`[EnemyController] 当前生成间隔: ${this.spawnInterval}`);
         
         this.updateWaveLabel();
         this.updateEnemyCountLabel();

+ 2 - 2
assets/scripts/CombatSystem/GameEnd.ts

@@ -233,7 +233,7 @@ export class GameEnd extends Component {
             this.diamondLabel.string = this.currentRewards.diamonds.toString();
         }
         
-        console.log(`[GameEnd] 更新奖励显示 - 金币: ${this.currentRewards.money}, 钻石: ${this.currentRewards.diamonds}`);
+        console.log(`[GameEnd] 更新奖励显示 - 钞票: ${this.currentRewards.money}, 钻石: ${this.currentRewards.diamonds}`);
     }
     
     /**
@@ -305,7 +305,7 @@ export class GameEnd extends Component {
             this.doubleButton.interactable = false;
         }
         
-        console.log(`[GameEnd] 双倍奖励已给予 - 额外金币: ${doubleMoney}, 额外钻石: ${doubleDiamonds}`);
+        console.log(`[GameEnd] 双倍奖励已给予 - 额外钞票: ${doubleMoney}, 额外钻石: ${doubleDiamonds}`);
         
         // 触发货币变化事件
         EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);

+ 6 - 23
assets/scripts/CombatSystem/SkillSelection/SkillButtonAnimator.ts

@@ -9,9 +9,11 @@ const { ccclass, property } = _decorator;
 @ccclass('SkillButtonAnimator')
 export class SkillButtonAnimator extends Component {
 
+    @property({ type: [Node], tooltip: '星星节点数组 (xx-1 到 xx-5)' })
+    starNodes: Node[] = [];
+
     private _origScale: Vec3 = new Vec3();
     private _origPos: Vec3 = new Vec3();
-    private _starNodes: Node[] = [];
     private _blinkTween: any = null;
     
     // 星星颜色配置
@@ -22,25 +24,6 @@ export class SkillButtonAnimator extends Component {
         // 记录初始位置、缩放,用于恢复
         this._origScale.set(this.node.scale);
         this._origPos.set(this.node.position);
-        
-        // 查找星星节点
-        this.findStarNodes();
-    }
-
-    /**
-     * 查找星星节点
-     */
-    private findStarNodes() {
-        const starContainer = this.node.getChildByName('Star');
-        if (starContainer) {
-            // 查找所有星星节点 (xx-1, xx-2, xx-3, xx-4, xx-5)
-            for (let i = 1; i <= 5; i++) {
-                const starNode = starContainer.getChildByName(`xx-${i}`);
-                if (starNode) {
-                    this._starNodes.push(starNode);
-                }
-            }
-        }
     }
 
     /**
@@ -52,7 +35,7 @@ export class SkillButtonAnimator extends Component {
         this.stopBlinkAnimation();
         
         // 更新星星显示
-        this._starNodes.forEach((starNode, index) => {
+        this.starNodes.forEach((starNode, index) => {
             const sprite = starNode.getComponent(Sprite);
             if (sprite) {
                 if (index < currentLevel) {
@@ -79,9 +62,9 @@ export class SkillButtonAnimator extends Component {
      * @param nextStarIndex 下一颗要闪烁的星星索引 (0-4)
      */
     private startBlinkAnimation(nextStarIndex: number) {
-        if (nextStarIndex >= this._starNodes.length) return;
+        if (nextStarIndex >= this.starNodes.length) return;
         
-        const nextStar = this._starNodes[nextStarIndex];
+        const nextStar = this.starNodes[nextStarIndex];
         const sprite = nextStar.getComponent(Sprite);
         if (!sprite) return;
         

+ 216 - 0
assets/scripts/CombatSystem/SkillSelection/SkillButtonController.ts

@@ -0,0 +1,216 @@
+import { _decorator, Component, Node, Button, Label, Sprite, resources, SpriteFrame } from 'cc';
+import { SkillManager, SkillData } from './SkillManager';
+import { SkillButtonAnimator } from './SkillButtonAnimator';
+
+const { ccclass, property } = _decorator;
+
+/**
+ * SkillButtonController
+ * 单个技能按钮的控制器,负责显示技能信息和处理点击事件
+ * 配合预制体使用,提高代码复用性和维护性
+ */
+@ccclass('SkillButtonController')
+export class SkillButtonController extends Component {
+
+    @property({ type: Node, tooltip: '技能图标节点' })
+    public skillSpriteNode: Node = null!;
+
+    @property({ type: Node, tooltip: '技能名称节点' })
+    public skillNameNode: Node = null!;
+
+    @property({ type: Node, tooltip: '技能介绍节点' })
+    public skillIntroduceNode: Node = null!;
+
+    // 当前技能数据
+    private _skillData: SkillData | null = null;
+    // 按钮组件
+    private _button: Button | null = null;
+    // 动画组件
+    private _animator: SkillButtonAnimator | null = null;
+    // 点击回调
+    private _onClickCallback: ((skillButton: SkillButtonController) => void) | null = null;
+
+    protected onLoad() {
+        this._button = this.getComponent(Button);
+        this._animator = this.getComponent(SkillButtonAnimator);
+        
+        // 如果没有手动设置节点引用,尝试自动查找
+        if (!this.skillSpriteNode) {
+            this.skillSpriteNode = this.node.getChildByName('SkillSprite');
+        }
+        if (!this.skillNameNode) {
+            this.skillNameNode = this.node.getChildByName('SkillName');
+        }
+        if (!this.skillIntroduceNode && this.skillNameNode) {
+            this.skillIntroduceNode = this.skillNameNode.getChildByName('SkillIntroduce');
+        }
+    }
+
+    protected start() {
+        if (this._button) {
+            this._button.node.on(Button.EventType.CLICK, this.onButtonClick, this);
+        }
+    }
+
+    protected onDestroy() {
+        if (this._button) {
+            this._button.node.off(Button.EventType.CLICK, this.onButtonClick, this);
+        }
+    }
+
+    /**
+     * 设置技能数据并更新UI显示
+     */
+    public setSkillData(skillData: SkillData) {
+        this._skillData = skillData;
+        this.updateUI();
+    }
+
+    /**
+     * 获取当前技能数据
+     */
+    public getSkillData(): SkillData | null {
+        return this._skillData;
+    }
+
+    /**
+     * 设置点击回调
+     */
+    public setClickCallback(callback: (skillButton: SkillButtonController) => void) {
+        this._onClickCallback = callback;
+    }
+
+    /**
+     * 更新UI显示
+     */
+    private updateUI() {
+        if (!this._skillData) {
+            this.node.active = false;
+            return;
+        }
+
+        this.node.active = true;
+
+        // 更新技能图标
+        this.updateSkillIcon();
+        
+        // 更新技能名称
+        this.updateSkillName();
+        
+        // 更新技能介绍
+        this.updateSkillDescription();
+        
+        // 更新星级显示
+        this.updateSkillLevel();
+    }
+
+    /**
+     * 更新技能图标
+     */
+    private updateSkillIcon() {
+        if (!this.skillSpriteNode || !this._skillData) return;
+
+        const sprite = this.skillSpriteNode.getComponent(Sprite);
+        if (sprite) {
+            const framePath = `${this._skillData.iconPath}/spriteFrame`;
+            resources.load(framePath, SpriteFrame, (err, spriteFrame) => {
+                if (!err && spriteFrame && sprite && sprite.isValid) {
+                    sprite.spriteFrame = spriteFrame;
+                    console.log(`技能图标加载成功: ${this._skillData!.iconPath}`);
+                } else if (err) {
+                    console.warn(`加载技能图标失败: ${this._skillData!.iconPath}`, err);
+                }
+            });
+        }
+    }
+
+    /**
+     * 更新技能名称
+     */
+    private updateSkillName() {
+        if (!this.skillNameNode || !this._skillData) return;
+
+        const label = this.skillNameNode.getComponent(Label);
+        if (label) {
+            label.string = this._skillData.name;
+        }
+    }
+
+    /**
+     * 更新技能介绍
+     */
+    private updateSkillDescription() {
+        if (!this.skillIntroduceNode || !this._skillData) return;
+
+        const label = this.skillIntroduceNode.getComponent(Label);
+        if (label) {
+            const skillManager = SkillManager.getInstance();
+            if (skillManager) {
+                // 获取当前技能等级的描述
+                const currentLevel = skillManager.getSkillLevel(this._skillData.id);
+                const description = skillManager.getSkillDescription(this._skillData.id, currentLevel);
+                label.string = description;
+            } else {
+                label.string = this._skillData.description;
+            }
+        }
+    }
+
+    /**
+     * 更新技能等级显示
+     */
+    private updateSkillLevel() {
+        if (!this._animator || !this._skillData) return;
+
+        const skillManager = SkillManager.getInstance();
+        const actualLevel = skillManager ? skillManager.getSkillLevel(this._skillData.id) : 0;
+        this._animator.setSkillLevel(actualLevel);
+        console.log(`设置技能 ${this._skillData.name} 星级: ${actualLevel}`);
+    }
+
+    /**
+     * 刷新技能等级显示(用于技能升级后的UI更新)
+     */
+    public refreshSkillLevel() {
+        this.updateSkillLevel();
+        this.updateSkillDescription(); // 同时更新描述
+    }
+
+    /**
+     * 按钮点击事件
+     */
+    private onButtonClick() {
+        if (this._onClickCallback) {
+            this._onClickCallback(this);
+        }
+    }
+
+    /**
+     * 播放收缩动画
+     */
+    public playShrinkAnimation(duration: number, targetPos?: any, onComplete?: () => void) {
+        if (this._animator) {
+            this._animator.playShrink(duration, targetPos, onComplete);
+        } else if (onComplete) {
+            onComplete();
+        }
+    }
+
+    /**
+     * 重置动画状态
+     */
+    public resetAnimationState() {
+        if (this._animator) {
+            this._animator.resetState();
+        }
+    }
+
+    /**
+     * 设置按钮交互状态
+     */
+    public setInteractable(interactable: boolean) {
+        if (this._button) {
+            this._button.interactable = interactable;
+        }
+    }
+}

+ 9 - 0
assets/scripts/CombatSystem/SkillSelection/SkillButtonController.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "66ff2880-2ebc-46a8-8b36-2f520f19cf6c",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 96 - 10
assets/scripts/CombatSystem/SkillSelection/SkillManager.ts

@@ -1,6 +1,14 @@
 import { _decorator, Component, Node } from 'cc';
 const { ccclass, property } = _decorator;
 
+/**
+ * 技能等级效果配置接口
+ */
+export interface SkillLevelEffects {
+    descriptions: string[];
+    [effectName: string]: number[] | string[];
+}
+
 /**
  * 技能数据接口
  */
@@ -11,7 +19,7 @@ export interface SkillData {
     iconPath: string;
     maxLevel: number;
     currentLevel: number;
-    effects: any;
+    levelEffects: SkillLevelEffects;
 }
 
 /**
@@ -102,7 +110,10 @@ export class SkillManager extends Component {
      */
     public static calculateCheaperUnitsPrice(originalPrice: number, skillLevel: number): number {
         if (skillLevel <= 0) return originalPrice;
-        const reductionRate = skillLevel * 0.1;
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return originalPrice;
+        
+        const reductionRate = skillManager.getSkillEffectValue('cheaper_units', 'priceReduction', skillLevel);
         return originalPrice * (1 - reductionRate);
     }
 
@@ -111,7 +122,10 @@ export class SkillManager extends Component {
      */
     public static calculateCritChance(baseCritChance: number, skillLevel: number): number {
         if (skillLevel <= 0) return baseCritChance;
-        const bonusCritChance = skillLevel * 0.1;
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return baseCritChance;
+        
+        const bonusCritChance = skillManager.getSkillEffectValue('crit_chance', 'critChanceIncrease', skillLevel);
         return Math.min(1.0, baseCritChance + bonusCritChance);
     }
 
@@ -120,7 +134,11 @@ export class SkillManager extends Component {
      */
     public static calculateCritDamage(baseDamage: number, skillLevel: number): number {
         if (skillLevel <= 0) return baseDamage;
-        const critMultiplier = 1 + (skillLevel * 0.1);
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return baseDamage;
+        
+        const critDamageBonus = skillManager.getSkillEffectValue('crit_chance', 'critChanceIncrease', skillLevel);
+        const critMultiplier = 1 + critDamageBonus;
         return baseDamage * critMultiplier;
     }
 
@@ -129,7 +147,10 @@ export class SkillManager extends Component {
      */
     public static calculateHealBonus(baseHealth: number, skillLevel: number): number {
         if (skillLevel <= 0) return baseHealth;
-        const healthBonus = skillLevel * 0.1;
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return baseHealth;
+        
+        const healthBonus = skillManager.getSkillEffectValue('heal', 'healthIncrease', skillLevel);
         return Math.floor(baseHealth * (1 + healthBonus));
     }
     
@@ -138,7 +159,11 @@ export class SkillManager extends Component {
      */
     public static calculateInstantHeal(maxHealth: number, skillLevel: number): number {
         if (skillLevel <= 0) return 0;
-        return Math.floor(maxHealth * 0.1 * skillLevel);
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return 0;
+        
+        const healthBonus = skillManager.getSkillEffectValue('heal', 'healthIncrease', skillLevel);
+        return Math.floor(maxHealth * healthBonus);
     }
     
     /**
@@ -146,7 +171,10 @@ export class SkillManager extends Component {
      */
     public static getHealSkillHealthBonus(skillLevel: number): number {
         if (skillLevel <= 0) return 0;
-        return skillLevel * 0.1;
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return 0;
+        
+        return skillManager.getSkillEffectValue('heal', 'healthIncrease', skillLevel);
     }
 
     /**
@@ -154,7 +182,10 @@ export class SkillManager extends Component {
      */
     public static calculateMultiShotChance(baseMultiShotChance: number, skillLevel: number): number {
         if (skillLevel <= 0) return baseMultiShotChance;
-        const bonusChance = skillLevel * 0.1;
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return baseMultiShotChance;
+        
+        const bonusChance = skillManager.getSkillEffectValue('multi_shots', 'multiShotChance', skillLevel);
         return Math.min(1.0, baseMultiShotChance + bonusChance);
     }
 
@@ -163,6 +194,7 @@ export class SkillManager extends Component {
      */
     public static calculateMultiShotBulletCount(baseBulletCount: number, skillLevel: number): number {
         if (skillLevel <= 0) return baseBulletCount;
+        // 这个方法保持原有逻辑,因为配置中没有对应的子弹数量配置
         return baseBulletCount + Math.floor(skillLevel / 2);
     }
 
@@ -171,7 +203,11 @@ export class SkillManager extends Component {
      */
     public static calculateEnergyBonus(baseEnergy: number, skillLevel: number): number {
         if (skillLevel <= 0) return baseEnergy;
-        const energyMultiplier = 1 + (skillLevel * 0.1);
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return baseEnergy;
+        
+        const energyBonus = skillManager.getSkillEffectValue('energy_hunter', 'energyGainIncrease', skillLevel);
+        const energyMultiplier = 1 + energyBonus;
         return baseEnergy * energyMultiplier;
     }
 
@@ -180,7 +216,11 @@ export class SkillManager extends Component {
      */
     public static calculateBallSpeed(baseBallSpeed: number, skillLevel: number): number {
         if (skillLevel <= 0) return baseBallSpeed;
-        const speedMultiplier = 1 + (skillLevel * 0.1);
+        const skillManager = SkillManager.getInstance();
+        if (!skillManager) return baseBallSpeed;
+        
+        const speedBonus = skillManager.getSkillEffectValue('ball_speed', 'ballSpeedIncrease', skillLevel);
+        const speedMultiplier = 1 + speedBonus;
         return baseBallSpeed * speedMultiplier;
     }
 
@@ -236,6 +276,52 @@ export class SkillManager extends Component {
         }
     }
 
+    /**
+     * 获取技能在指定等级的效果值
+     */
+    public getSkillEffectValue(skillId: string, effectName: string, level: number): number {
+        const skill = this._skills.get(skillId);
+        if (!skill || !skill.levelEffects || !skill.levelEffects[effectName]) {
+            console.warn(`[SkillManager] 技能 ${skillId} 的效果 ${effectName} 不存在`);
+            return 0;
+        }
+        
+        const effectArray = skill.levelEffects[effectName] as number[];
+        if (level < 0 || level >= effectArray.length) {
+            console.warn(`[SkillManager] 技能 ${skillId} 等级 ${level} 超出范围`);
+            return 0;
+        }
+        
+        return effectArray[level];
+    }
+    
+    /**
+     * 获取技能在指定等级的描述
+     */
+    public getSkillDescription(skillId: string, level: number): string {
+        const skill = this._skills.get(skillId);
+        if (!skill || !skill.levelEffects || !skill.levelEffects.descriptions) {
+            return skill?.description || '';
+        }
+        
+        const descriptions = skill.levelEffects.descriptions;
+        if (level < 0 || level >= descriptions.length) {
+            return skill.description;
+        }
+        
+        return descriptions[level];
+    }
+    
+    /**
+     * 获取技能当前等级的描述
+     */
+    public getCurrentSkillDescription(skillId: string): string {
+        const skill = this._skills.get(skillId);
+        if (!skill) return '';
+        
+        return this.getSkillDescription(skillId, skill.currentLevel);
+    }
+
     /**
      * 获取所有技能数据(用于保存)
      */

+ 29 - 76
assets/scripts/CombatSystem/SkillSelection/SkillSelectionController.ts

@@ -1,12 +1,10 @@
-import { _decorator, Component, Node, Button, find, Label, Sprite, Vec3, CCFloat, resources, JsonAsset, SpriteFrame } from 'cc';
+import { _decorator, Component, Node, find, CCFloat, resources, JsonAsset } from 'cc';
 import { GameManager } from '../../LevelSystem/GameManager';
 import { InGameManager } from '../../LevelSystem/IN_game';
-import { SkillButtonAnimator } from './SkillButtonAnimator';
-// GamePause已通过事件系统解耦,不再需要直接导入
+import { SkillButtonController } from './SkillButtonController';
 import { SkillManager, SkillData } from './SkillManager';
 import { Wall } from '../Wall';
 import { EnemyController } from '../EnemyController';
-import EventBus, { GameEvents } from '../../Core/EventBus';
 
 const { ccclass, property } = _decorator;
 
@@ -24,8 +22,8 @@ interface SkillConfig {
 @ccclass('SkillSelectionController')
 export class SkillSelectionController extends Component {
 
-    @property({ type: [Node], tooltip: '技能按钮节点列表,留空则自动从 SkillsContainer 获取' })
-    public skillButtons: Node[] = [];
+    @property({ type: [SkillButtonController], tooltip: '技能按钮控制器列表,留空则自动从 SkillsContainer 获取' })
+    public skillButtons: SkillButtonController[] = [];
 
     @property({ type: CCFloat, tooltip: '收缩动画时长' })
     public shrinkDuration: number = 0.3;
@@ -70,15 +68,14 @@ export class SkillSelectionController extends Component {
         if (this.skillButtons.length === 0) {
             const container = this.node.getChildByName('SkillsContainer');
             if (container) {
-                this.skillButtons = container.children.slice();
+                this.skillButtons = container.children
+                    .map(child => child.getComponent(SkillButtonController))
+                    .filter(controller => controller !== null) as SkillButtonController[];
             }
         }
 
-        this.skillButtons.forEach(btnNode => {
-            const btn = btnNode.getComponent(Button);
-            if (btn) {
-                btn.node.on(Button.EventType.CLICK, () => this.onSkillSelected(btnNode), this);
-            }
+        this.skillButtons.forEach(skillButton => {
+            skillButton.setClickCallback((selectedButton) => this.onSkillSelected(selectedButton));
         });
     }
 
@@ -108,58 +105,19 @@ export class SkillSelectionController extends Component {
      * 更新技能UI显示
      */
     private updateSkillUI() {
-        this.skillButtons.forEach((btnNode, index) => {
+        this.skillButtons.forEach((skillButton, index) => {
             if (index < this._currentSkills.length) {
                 const skillData = this._currentSkills[index];
+                skillButton.setSkillData(skillData);
                 
-                // 更新技能图标
-                const skillSprite = btnNode.getChildByName('SkillSprite');
-                if (skillSprite) {
-                    const sprite = skillSprite.getComponent(Sprite);
-                    if (sprite) {
-                        // 加载技能图标 - 参考UpgradeController的加载方式,在路径后添加'/spriteFrame'
-                        const framePath = `${skillData.iconPath}/spriteFrame`;
-                        resources.load(framePath, SpriteFrame, (err, spriteFrame) => {
-                            if (!err && spriteFrame && sprite && sprite.isValid) {
-                                sprite.spriteFrame = spriteFrame;
-                                console.log(`技能图标加载成功: ${skillData.iconPath}`);
-                            } else if (err) {
-                                console.warn(`加载技能图标失败: ${skillData.iconPath}`, err);
-                            }
-                        });
-                    }
-                }
-                
-                // 更新技能名称
-                const skillName = btnNode.getChildByName('SkillName');
-                if (skillName) {
-                    const label = skillName.getComponent(Label);
-                    if (label) {
-                        label.string = skillData.name;
-                    }
-                }
-                
-                // 更新技能介绍
-                const skillIntroduce = btnNode.getChildByName('SkillIntroduce');
-                if (skillIntroduce) {
-                    const label = skillIntroduce.getComponent(Label);
-                    if (label) {
-                        label.string = skillData.description;
-                    }
-                }
-                
-                // 设置星级显示 - 从SkillManager获取实际的技能等级
-                const animator = btnNode.getComponent(SkillButtonAnimator);
-                if (animator) {
-                    const skillManager = SkillManager.getInstance();
-                    const actualLevel = skillManager ? skillManager.getSkillLevel(skillData.id) : 0;
-                    animator.setSkillLevel(actualLevel);
-                    console.log(`设置技能 ${skillData.name} 星级: ${actualLevel}`);
+                // 确保显示当前等级的描述
+                const skillManager = SkillManager.getInstance();
+                if (skillManager) {
+                    const currentLevel = skillManager.getSkillLevel(skillData.id);
+                    console.log(`[SkillSelectionController] 技能 ${skillData.name} 当前等级: ${currentLevel}`);
                 }
-                
-                btnNode.active = true;
             } else {
-                btnNode.active = false;
+                skillButton.setSkillData(null);
             }
         });
     }
@@ -167,22 +125,20 @@ export class SkillSelectionController extends Component {
     /**
      * 玩家选择某技能按钮
      */
-    private onSkillSelected(selectedBtn: Node) {
+    private onSkillSelected(selectedButton: SkillButtonController) {
         if (this._clicked) return;
         this._clicked = true;
 
         // 获取选中的技能
-        const btnIndex = this.skillButtons.indexOf(selectedBtn);
-        if (btnIndex >= 0 && btnIndex < this._currentSkills.length) {
-            const selectedSkill = this._currentSkills[btnIndex];
-            
+        const selectedSkill = selectedButton.getSkillData();
+        if (selectedSkill) {
             // 通过技能管理器升级技能
             const skillManager = SkillManager.getInstance();
             if (skillManager) {
                 skillManager.upgradeSkill(selectedSkill.id);
                 
                 // 立即更新UI显示新的星级
-                this.updateSkillUI();
+                this.skillButtons.forEach(btn => btn.refreshSkillLevel());
                 
                 // 如果是治疗技能,立即应用治疗效果
                 if (selectedSkill.id === 'heal') {
@@ -191,16 +147,15 @@ export class SkillSelectionController extends Component {
             }
         }
 
-        const otherBtns = this.skillButtons.filter(btn => btn !== selectedBtn);
+        const otherButtons = this.skillButtons.filter(btn => btn !== selectedButton);
         let finishedOthers = 0;
 
         // 所有其他按钮完成动画后,再收缩选中按钮
         const onOtherFinished = () => {
             finishedOthers++;
-            if (finishedOthers >= otherBtns.length) {
+            if (finishedOthers >= otherButtons.length) {
                 // 收缩选中按钮
-                const selAnim = selectedBtn.getComponent(SkillButtonAnimator);
-                selAnim?.playShrink(this.shrinkDuration, undefined, () => {
+                selectedButton.playShrinkAnimation(this.shrinkDuration, undefined, () => {
                     const igm = this.getInGameManager();
                     if (igm) {
                         igm.resetEnergyValue();
@@ -217,10 +172,9 @@ export class SkillSelectionController extends Component {
         };
 
         // 播放其他按钮动画
-        const targetPos = selectedBtn.position.clone();
-        otherBtns.forEach(btn => {
-            const anim = btn.getComponent(SkillButtonAnimator);
-            anim?.playShrink(this.shrinkDuration, targetPos, onOtherFinished);
+        const targetPos = selectedButton.node.position.clone();
+        otherButtons.forEach(btn => {
+            btn.playShrinkAnimation(this.shrinkDuration, targetPos, onOtherFinished);
         });
     }
 
@@ -232,9 +186,8 @@ export class SkillSelectionController extends Component {
 
         // 重新启用所有按钮交互
         this.skillButtons.forEach(btn => {
-            // 重置按钮动画状态
-            const anim = btn.getComponent(SkillButtonAnimator);
-            anim?.resetState();
+            btn.resetAnimationState();
+            btn.setInteractable(true);
         });
         
         // 重新随机选择技能

+ 1 - 1
assets/scripts/CombatSystem/Wall.ts

@@ -277,7 +277,7 @@ export class Wall extends Component {
         // 检查是否可以升级
         if (!this.saveDataManager.canUpgradeWall()) return null;
 
-        // 获取升级费用并扣除金币
+        // 获取升级费用并扣除钞票
         const cost = this.saveDataManager.getWallUpgradeCost();
         if (!this.saveDataManager.spendMoney(cost)) return null;
 

+ 1 - 1
assets/scripts/CombatSystem/WeaponBullet.ts

@@ -700,7 +700,7 @@ export class WeaponBullet extends Component {
             case 'common':
                 return 1; // 1级,无倍数
             case 'uncommon':
-                return 2; // 2级,2倍伤害
+                return 1.5; // 2级,2倍伤害
             case 'rare':
                 return 4; // 3级,4倍伤害
             case 'epic':

+ 0 - 7
assets/scripts/Core/ConfigManager.ts

@@ -354,13 +354,6 @@ export class ConfigManager extends BaseSingleton {
         });
     }
 
-    // 加载球控制器配置
-    // 球控制器配置现在通过BallController组件的装饰器直接加载,不再需要在ConfigManager中处理
-
-
-
-
-
     // 随机获取武器配置
     public getRandomWeapon(rarity?: string): WeaponConfig | null {
         if (!this.weaponsConfig || !this.weaponsConfig.weapons || this.weaponsConfig.weapons.length === 0) {

+ 7 - 7
assets/scripts/FourUI/MainSystem/MainUIControlller.ts

@@ -12,13 +12,13 @@ const { ccclass, property } = _decorator;
 @ccclass('MainUIController')
 export class MainUIController extends Component {
   /* 奖励节点 */
-  @property(Node) rewardMoneyNode: Node = null;      // 左金币奖励
+  @property(Node) rewardMoneyNode: Node = null;      // 左钞票奖励
   @property(Node) rewardDiamondNode: Node = null;    // 右钻石奖励
   @property(Label) levelNumberLabel: Label = null;   // 第 X 关文本
 
   /* 升级 */
   @property(Button) upgradeBtn: Button = null;       // 升级按钮
-  @property(Node) upgradeCostLabel: Node = null;     // 消耗金币数字
+  @property(Node) upgradeCostLabel: Node = null;     // 消耗钞票数字
   @property(Node) upgradeHpLabel: Node = null;       // 升级后血量数字
 
   /* 主功能按钮 */
@@ -99,7 +99,7 @@ export class MainUIController extends Component {
     const currentWallLevel = this.sdm.getWallLevel();
     const upgradeCost = this.sdm.getWallUpgradeCost();
     
-    console.log(`[MainUIController] 当前状态: 金币=${currentMoney}, 墙体等级=${currentWallLevel}, 升级费用=${upgradeCost}`);
+    console.log(`[MainUIController] 当前状态: 钞票=${currentMoney}, 墙体等级=${currentWallLevel}, 升级费用=${upgradeCost}`);
     
     // 检查墙体等级是否已达到最大值
     const maxLevel = this.sdm.getWallMaxLevel();
@@ -112,7 +112,7 @@ export class MainUIController extends Component {
       return;
     }
     
-    // 检查金币是否足够
+    // 检查钞票是否足够
     if (currentMoney < upgradeCost) {
       EventBus.getInstance().emit(GameEvents.SHOW_TOAST, {
         message: `钞票不足,需要${upgradeCost}钞票`,
@@ -123,7 +123,7 @@ export class MainUIController extends Component {
 
     // 执行升级
     if (!this.sdm.spendMoney(upgradeCost)) {
-      console.log('[MainUIController] 扣除金币失败');
+      console.log('[MainUIController] 扣除钞票失败');
       return;
     }
 
@@ -201,7 +201,7 @@ export class MainUIController extends Component {
       const rewards = await this.sdm.getLevelRewardsFromConfig(currentLevel);
       
       if (rewards) {
-        // 更新金币奖励显示
+        // 更新钞票奖励显示
         if (this.rewardMoneyNode) {
           const coinLabel = this.rewardMoneyNode.getComponent(Label) || this.rewardMoneyNode.getComponentInChildren(Label);
           if (coinLabel) {
@@ -229,7 +229,7 @@ export class MainUIController extends Component {
 
   /** 设置默认奖励值 */
   private setDefaultRewards() {
-    // 金币奖励默认值
+    // 钞票奖励默认值
     if (this.rewardMoneyNode) {
       const coinLabel = this.rewardMoneyNode.getComponent(Label) || this.rewardMoneyNode.getComponentInChildren(Label);
       if (coinLabel) {

+ 5 - 5
assets/scripts/FourUI/TopBarController.ts

@@ -9,7 +9,7 @@ export class TopBarController extends Component {
   /* 顶部资源 & 关卡 */
   @property(Node) moneyAddBtn: Node = null;          // 绿色 +
   @property(Node) diamondAddBtn: Node = null;        // 紫色 +
-  @property(Node) moneyLabel: Node = null;           // 金币数字
+  @property(Node) moneyLabel: Node = null;           // 钞票数字
   @property(Node) diamondLabel: Node = null;         // 钻石数字
 
 
@@ -53,14 +53,14 @@ export class TopBarController extends Component {
 
   /* 绑定按钮事件 */
   private bindButtons() {
-    this.moneyAddBtn?.on(Button.EventType.CLICK, () => this.addCoins(100), this);
+    this.moneyAddBtn?.on(Button.EventType.CLICK, () => this.addMoney(100), this);
     this.diamondAddBtn?.on(Button.EventType.CLICK, () => this.addDiamonds(20), this);
 
 
   }
 
   /* ================= 业务逻辑 ================= */
-  private addCoins(v: number) { 
+  private addMoney(v: number) { 
     this.sdm.addMoney(v, 'ad'); 
     // 触发货币变化事件
     EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
@@ -88,13 +88,13 @@ export class TopBarController extends Component {
     const currentCoins = this.sdm.getMoney();
     const currentDiamonds = this.sdm.getDiamonds();
     
-    console.log(`[TopBarController] 刷新货币显示 - 金钱: ${currentCoins}, 钻石: ${currentDiamonds}`);
+    console.log(`[TopBarController] 刷新货币显示 - 钞票: ${currentCoins}, 钻石: ${currentDiamonds}`);
     
     const mLbl = this.moneyLabel?.getComponent(Label) || this.moneyLabel as unknown as Label;
     if (mLbl) {
       const formattedCoins = this.format(currentCoins);
       mLbl.string = formattedCoins;
-      console.log(`[TopBarController] 金钱显示更新为: ${formattedCoins}`);
+      console.log(`[TopBarController] 钞票显示更新为: ${formattedCoins}`);
     }
     
     const dLbl = this.diamondLabel?.getComponent(Label) || this.diamondLabel as unknown as Label;

+ 6 - 6
assets/scripts/FourUI/UpgradeSystem/UpgradeController.ts

@@ -756,8 +756,8 @@ export class UpgradeController extends Component {
         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] 升级检查 - 武器: ${this.currentSelectedWeapon}, 费用: ${cost}, 当前钞票: ${playerMoney}`);
+        console.log(`[UpgradeController] 费用类型: ${typeof cost}, 钞票类型: ${typeof playerMoney}`);
         console.log(`[UpgradeController] 条件判断: ${playerMoney} < ${cost} = ${playerMoney < cost}`);
         
         if (playerMoney < cost) {
@@ -766,18 +766,18 @@ export class UpgradeController extends Component {
             return;
         }
         
-        console.log(`[UpgradeController] 金币充足,继续升级流程`);
+        console.log(`[UpgradeController] 钞票充足,继续升级流程`);
         
-        // 记录升级前的金币数量
+        // 记录升级前的钞票数量
         const coinsBeforeUpgrade = this.saveDataManager.getMoney();
-        console.log(`[UpgradeController] 升级前金币: ${coinsBeforeUpgrade}`);
+        console.log(`[UpgradeController] 升级前钞票: ${coinsBeforeUpgrade}`);
         
         const success = this.saveDataManager.upgradeWeapon(this.currentSelectedWeapon);
         
         if (success) {
             const coinsAfterUpgrade = this.saveDataManager.getMoney();
             console.log(`[UpgradeController] 武器 ${this.currentSelectedWeapon} 升级成功`);
-            console.log(`[UpgradeController] 升级后金币: ${coinsAfterUpgrade}, 消耗: ${coinsBeforeUpgrade - coinsAfterUpgrade}`);
+            console.log(`[UpgradeController] 升级后钞票: ${coinsAfterUpgrade}, 消耗: ${coinsBeforeUpgrade - coinsAfterUpgrade}`);
             
             // 播放武器升级成功动画
             this.playWeaponUpgradeSuccessAnimation();

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

@@ -178,7 +178,7 @@ export class GameManager extends Component {
         // 先初始化UI节点,确保inGameManager可用
         this.initUINodes();
         
-        // 提前初始化本局数据,确保 BlockManager 在 start 时能拿到正确金币
+        // 提前初始化本局数据,确保 BlockManager 在 start 时能拿到正确的局内金币
         if (!LevelSessionManager.inst.runtime) {
             LevelSessionManager.inst.initialize(
                 this.saveDataManager?.getCurrentLevel() || 1,
@@ -897,7 +897,7 @@ export class GameManager extends Component {
             data: levelData,
             config: levelConfig,
             playerData: this.saveDataManager ? {
-                coins: this.saveDataManager.getMoney(),
+                money: this.saveDataManager.getMoney(),
                 diamonds: this.saveDataManager.getDiamonds(),
                 wallLevel: this.saveDataManager.getWallLevel()
             } : null

+ 1 - 1
assets/scripts/LevelSystem/IN_game.ts

@@ -938,7 +938,7 @@ export class InGameManager extends Component {
             this.selectSkillUI.active = false;
         }
         
-        // 6. 清理会话数据(金币等临时数据)
+        // 6. 清理会话数据(局内金币等临时数据)
         console.log('[InGameManager] 清理会话数据');
         if (LevelSessionManager.inst) {
             LevelSessionManager.inst.clear(); // 清空局内金币等临时数据

+ 9 - 9
assets/scripts/LevelSystem/SaveDataManager.ts

@@ -30,7 +30,7 @@ export interface PlayerData {
     totalPlayTime: number;
     
     // 货币系统
-    money: number;           // 局外金币
+    money: number;           // 局外钞票
     diamonds: number;        // 钻石
 
     // 墙体等级系统
@@ -637,7 +637,7 @@ export class SaveDataManager {
     // === 货币管理 ===
     
     /**
-     * 添加局外金币
+     * 添加局外钞票
      */
     public addMoney(amount: number, source: string = 'unknown'): boolean {
         if (!this.playerData || amount <= 0) return false;
@@ -657,7 +657,7 @@ export class SaveDataManager {
     }
     
     /**
-     * 消费局外金币
+     * 消费局外钞票
      */
     public spendMoney(amount: number): boolean {
         if (!this.playerData || amount <= 0) {
@@ -1090,7 +1090,7 @@ export class SaveDataManager {
             if (configRewards.money > 0) {
                 this.addMoney(configRewards.money, `level_${levelId}_complete`);
                 actualCoins = configRewards.money;
-                console.log(`[SaveDataManager] 添加金币: ${configRewards.money}`);
+                console.log(`[SaveDataManager] 添加钞票: ${configRewards.money}`);
             }
             if (configRewards.diamonds > 0) {
                 this.addDiamonds(configRewards.diamonds, `level_${levelId}_complete`);
@@ -1141,8 +1141,8 @@ export class SaveDataManager {
             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}`);
+            console.log(`[SaveDataManager] 基于配置计算奖励 - 原始钞票: ${configRewards.money}, 原始钻石: ${configRewards.diamonds}`);
+        console.log(`[SaveDataManager] 计算出的失败奖励 - 钞票: ${partialCoins}, 钻石: ${partialDiamonds}`);
             
             if (partialCoins > 0) {
                 this.addMoney(partialCoins, `level_${levelId}_partial_${actualCompletedWaves}/${totalWaves}`);
@@ -1157,7 +1157,7 @@ export class SaveDataManager {
             const baseCoins = levelId * 50;
             const partialCoins = Math.floor(baseCoins * waveRatio);
             
-            console.log(`[SaveDataManager] 使用默认计算 - 基础金币: ${baseCoins}, 计算出的失败奖励: ${partialCoins}`);
+            console.log(`[SaveDataManager] 使用默认计算 - 基础钞票: ${baseCoins}, 计算出的失败奖励: ${partialCoins}`);
             
             if (partialCoins > 0) {
                 this.addMoney(partialCoins, `level_${levelId}_partial_${actualCompletedWaves}/${totalWaves}`);
@@ -1165,7 +1165,7 @@ export class SaveDataManager {
             }
         }
         
-        console.log(`[SaveDataManager] 最终失败奖励 - 金币: ${actualCoins}, 钻石: ${actualDiamonds}`);
+        console.log(`[SaveDataManager] 最终失败奖励 - 钞票: ${actualCoins}, 钻石: ${actualDiamonds}`);
         
         // 存储最近的奖励记录
         this.lastRewards = {money: actualCoins, diamonds: actualDiamonds};
@@ -1250,7 +1250,7 @@ export class SaveDataManager {
         return `墙体等级: ${this.playerData.wallLevel} | ` +
                `当前关卡: ${this.playerData.currentLevel} | ` +
                `最高关卡: ${this.playerData.maxUnlockedLevel} | ` +
-               `局外金币: ${this.playerData.money} | ` +
+               `局外钞票: ${this.playerData.money} | ` +
                `钻石: ${this.playerData.diamonds} | ` +
                `游戏次数: ${this.playerData.statistics.totalGamesPlayed}`;
     }

+ 65 - 0
test_skill_system.js

@@ -0,0 +1,65 @@
+/**
+ * 技能系统配置测试脚本
+ * 用于验证新的多星级技能效果配置是否正常工作
+ */
+
+const fs = require('fs');
+const path = require('path');
+
+// 读取技能配置文件
+const skillConfigPath = path.join(__dirname, 'assets/resources/data/skill.json');
+
+try {
+    const skillData = JSON.parse(fs.readFileSync(skillConfigPath, 'utf8'));
+    
+    console.log('=== 技能配置验证 ===');
+    
+    skillData.skills.forEach(skill => {
+        console.log(`\n技能: ${skill.name} (${skill.id})`);
+        console.log(`最大等级: ${skill.maxLevel}`);
+        
+        // 验证levelEffects结构
+        if (skill.levelEffects) {
+            console.log('等级效果配置:');
+            
+            Object.keys(skill.levelEffects).forEach(effectName => {
+                if (effectName === 'descriptions') {
+                    console.log(`  ${effectName}: ${skill.levelEffects[effectName].length} 个描述`);
+                    skill.levelEffects[effectName].forEach((desc, index) => {
+                        console.log(`    等级${index}: ${desc}`);
+                    });
+                } else {
+                    const values = skill.levelEffects[effectName];
+                    console.log(`  ${effectName}: [${values.join(', ')}]`);
+                    
+                    // 验证数组长度是否正确(应该是maxLevel + 1)
+                    if (values.length !== skill.maxLevel + 1) {
+                        console.error(`    ❌ 错误: ${effectName} 数组长度 ${values.length} 不等于 ${skill.maxLevel + 1}`);
+                    } else {
+                        console.log(`    ✅ 数组长度正确`);
+                    }
+                }
+            });
+        } else {
+            console.error('❌ 缺少 levelEffects 配置');
+        }
+    });
+    
+    console.log('\n=== 效果值测试 ===');
+    
+    // 测试暴击几率技能的不同等级效果
+    const critSkill = skillData.skills.find(s => s.id === 'crit_chance');
+    if (critSkill) {
+        console.log('\n暴击几率技能各等级效果:');
+        for (let level = 0; level <= critSkill.maxLevel; level++) {
+            const effectValue = critSkill.levelEffects.critChanceIncrease[level];
+            const description = critSkill.levelEffects.descriptions[level];
+            console.log(`  ${level}星: ${effectValue * 100}% - ${description}`);
+        }
+    }
+    
+    console.log('\n✅ 技能配置验证完成');
+    
+} catch (error) {
+    console.error('❌ 读取技能配置失败:', error.message);
+}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini