UpgradeController.ts 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195
  1. import { _decorator, Component, Node, Button, Label, Sprite, SpriteFrame, Texture2D, resources, ScrollView, Layout, Prefab, instantiate, find, UIOpacity, Color } from 'cc';
  2. import { BundleLoader } from '../../Core/BundleLoader';
  3. import { SaveDataManager, WeaponData } from '../../LevelSystem/SaveDataManager';
  4. import EventBus, { GameEvents } from '../../Core/EventBus';
  5. import { UpgradeAni } from './UpgradeAni';
  6. import { PopUPAni } from '../../Animations/PopUPAni';
  7. const { ccclass, property } = _decorator;
  8. /**
  9. * 武器配置接口(从weapons.json加载)
  10. */
  11. interface WeaponConfig {
  12. id: string;
  13. name: string;
  14. type: string;
  15. rarity: string;
  16. weight: number;
  17. stats: {
  18. damage: number;
  19. fireRate: number;
  20. range: number;
  21. bulletSpeed: number;
  22. };
  23. visualConfig: {
  24. weaponSprites: string | {
  25. "I": string;
  26. "H-I": string;
  27. "L": string;
  28. "S": string;
  29. "D-T": string;
  30. };
  31. };
  32. upgradeConfig?: {
  33. maxLevel: number;
  34. levels: {
  35. [level: string]: {
  36. cost: number;
  37. damage?: number;
  38. };
  39. };
  40. };
  41. }
  42. /**
  43. * 武器升级系统控制器
  44. * 负责管理武器升级UI和逻辑
  45. */
  46. @ccclass('UpgradeController')
  47. export class UpgradeController extends Component {
  48. // UI节点引用
  49. @property(Node) upgradeUI: Node = null; // Canvas/UpgradeUI
  50. @property(ScrollView) weaponScrollView: ScrollView = null; // Canvas/UpgradeUI/ScrollView
  51. @property(Layout) weaponLayout: Layout = null; // Canvas/UpgradeUI/ScrollView/view/content/Layout
  52. @property(Node) upgradePanel: Node = null; // Canvas/UpgradeUI/UpgradePanel
  53. @property(Button) closePanelBtn: Button = null; // Canvas/UpgradeUI/UpgradePanel/CloseBtn
  54. // 升级面板UI组件
  55. @property(Sprite) panelWeaponSprite: Sprite = null; // Canvas/UpgradeUI/UpgradePanel/WeaponSprite
  56. @property(Label) panelLevelLabel: Label = null; // Canvas/UpgradeUI/UpgradePanel/LevelLabel
  57. @property(Label) panelCurrentDamage: Label = null; // Canvas/UpgradeUI/UpgradePanel/NumberBack/CurrentDamage
  58. @property(Label) panelCostLabel: Label = null; // Canvas/UpgradeUI/UpgradePanel/UpgradeBtn/CostLabel
  59. @property(Button) panelUpgradeBtn: Button = null; // Canvas/UpgradeUI/UpgradePanel/UpgradeBtn
  60. // 武器节点预制体
  61. @property(Prefab) lockedWeaponPrefab: Prefab = null; // Lock.prefab
  62. @property(Prefab) unlockedWeaponPrefab: Prefab = null; // Unlock.prefab
  63. // 动画控制器
  64. @property(PopUPAni) upgradeAni: PopUPAni = null; // Canvas/UpgradeUI/UpgradePanel上的PopUPAni组件
  65. @property(UpgradeAni) weaponUpgradeAni: UpgradeAni = null; // 武器升级动画组件
  66. // 数据管理
  67. private saveDataManager: SaveDataManager = null;
  68. private weaponsConfig: { weapons: WeaponConfig[] } = null;
  69. private currentSelectedWeapon: string = null;
  70. private levelConfigs: any[] = [];
  71. private bundleLoader: BundleLoader = null;
  72. // 武器节点列表
  73. private weaponNodes: Node[] = [];
  74. onLoad() {
  75. this.saveDataManager = SaveDataManager.getInstance();
  76. this.bundleLoader = BundleLoader.getInstance();
  77. this.bindEvents();
  78. }
  79. async start() {
  80. // 先加载武器配置
  81. await this.loadWeaponsConfig();
  82. // 为UpgradeAni组件加载武器配置
  83. if (this.weaponUpgradeAni) {
  84. try {
  85. await this.weaponUpgradeAni.loadWeaponsConfig();
  86. console.log('[UpgradeController] UpgradeAni武器配置加载完成');
  87. } catch (error) {
  88. console.error('[UpgradeController] UpgradeAni武器配置加载失败:', error);
  89. }
  90. }
  91. // 加载关卡配置
  92. await this.loadLevelConfigs();
  93. // 初始化武器数据
  94. this.initializeWeapons();
  95. // 初始化时检查武器解锁状态
  96. this.checkInitialWeaponUnlocks();
  97. // 刷新UI
  98. await this.refreshWeaponList();
  99. // 初始化升级面板状态
  100. if (this.upgradeAni) {
  101. this.upgradeAni.hidePanelImmediate();
  102. } else {
  103. this.upgradePanel.active = false;
  104. }
  105. console.log('[UpgradeController] 初始化完成');
  106. }
  107. /**
  108. * 绑定事件
  109. */
  110. private bindEvents() {
  111. // 关闭升级面板
  112. this.closePanelBtn?.node.on(Button.EventType.CLICK, this.closeUpgradePanel, this);
  113. // 升级按钮
  114. this.panelUpgradeBtn?.node.on(Button.EventType.CLICK, this.onUpgradeWeapon, this);
  115. // 监听关卡完成事件,自动解锁武器
  116. EventBus.getInstance().on(GameEvents.GAME_SUCCESS, this.onLevelComplete, this);
  117. // 监听货币变化事件,更新升级按钮闪烁状态
  118. EventBus.getInstance().on(GameEvents.CURRENCY_CHANGED, this.onCurrencyChanged, this);
  119. }
  120. /**
  121. * 加载武器配置
  122. */
  123. private async loadWeaponsConfig() {
  124. try {
  125. const bundleLoader = BundleLoader.getInstance();
  126. const jsonAsset = await bundleLoader.loadDataJson('weapons');
  127. this.weaponsConfig = jsonAsset.json;
  128. console.log('[UpgradeController] 武器配置加载成功:', this.weaponsConfig);
  129. } catch (error) {
  130. console.error('[UpgradeController] 加载武器配置失败:', error);
  131. }
  132. }
  133. /**
  134. * 加载关卡配置
  135. */
  136. private async loadLevelConfigs() {
  137. try {
  138. this.levelConfigs = [];
  139. const bundleLoader = BundleLoader.getInstance();
  140. // 加载Level1到Level5的配置
  141. for (let i = 1; i <= 5; i++) {
  142. try {
  143. const levelData = await bundleLoader.loadDataJson(`levels/Level${i}`);
  144. this.levelConfigs.push({
  145. level: i,
  146. ...levelData.json
  147. });
  148. } catch (error) {
  149. console.warn(`加载Level${i}配置失败:`, error);
  150. }
  151. }
  152. console.log('关卡配置加载成功:', this.levelConfigs);
  153. } catch (error) {
  154. console.error('加载关卡配置失败:', error);
  155. this.levelConfigs = [];
  156. }
  157. }
  158. /**
  159. * 初始化武器数据(确保所有武器都在存档中)
  160. */
  161. private initializeWeapons() {
  162. if (!this.weaponsConfig) return;
  163. // 为每个武器创建初始数据(如果不存在)
  164. this.weaponsConfig.weapons.forEach(weaponConfig => {
  165. const existingWeapon = this.saveDataManager.getWeapon(weaponConfig.id);
  166. if (!existingWeapon) {
  167. this.saveDataManager.addWeapon(weaponConfig.id, weaponConfig.rarity);
  168. }
  169. });
  170. }
  171. /**
  172. * 初始化时检查武器解锁状态
  173. */
  174. private checkInitialWeaponUnlocks() {
  175. if (!this.saveDataManager || !this.weaponsConfig) return;
  176. const maxUnlockedLevel = this.saveDataManager.getMaxUnlockedLevel();
  177. console.log(`[UpgradeController] 初始化检查武器解锁状态,当前最大解锁关卡: ${maxUnlockedLevel}`);
  178. let hasUpdates = false;
  179. for (const weaponConfig of this.weaponsConfig.weapons) {
  180. const weaponId = weaponConfig.id;
  181. const weaponData = this.saveDataManager.getWeapon(weaponId);
  182. const requiredLevel = this.getWeaponUnlockLevelById(weaponId);
  183. // 检查武器是否应该根据关卡进度解锁
  184. const shouldBeUnlocked = maxUnlockedLevel >= requiredLevel;
  185. const isCurrentlyUnlocked = weaponData && weaponData.level > 0;
  186. // 如果武器应该解锁但还未解锁,则自动解锁
  187. if (shouldBeUnlocked && !isCurrentlyUnlocked && weaponData) {
  188. weaponData.level = 1;
  189. // 由于WeaponData类型中没有unlockTime属性,这里先注释掉
  190. // weaponData.unlockTime = weaponData.unlockTime || Date.now();
  191. console.log(`[UpgradeController] 初始化时自动解锁武器: ${weaponConfig.name} (${weaponId})`);
  192. hasUpdates = true;
  193. }
  194. }
  195. // 如果有更新,保存数据
  196. if (hasUpdates) {
  197. this.saveDataManager.savePlayerData();
  198. console.log(`[UpgradeController] 初始化武器解锁状态更新完成`);
  199. }
  200. }
  201. /**
  202. * 刷新武器列表UI
  203. */
  204. private async refreshWeaponList() {
  205. if (!this.weaponsConfig || !this.weaponLayout) {
  206. console.warn('武器配置或武器布局未初始化');
  207. return;
  208. }
  209. // 清除现有节点
  210. this.clearWeaponNodes();
  211. // 为每个武器创建UI节点
  212. for (let index = 0; index < this.weaponsConfig.weapons.length; index++) {
  213. const weaponConfig = this.weaponsConfig.weapons[index];
  214. await this.createWeaponNode(weaponConfig, index);
  215. }
  216. }
  217. /**
  218. * 切换武器节点状态(从锁定到解锁或反之)
  219. */
  220. private async switchWeaponNodeState(weaponId: string) {
  221. const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === weaponId);
  222. if (!weaponConfig) {
  223. console.warn(`未找到武器配置: ${weaponId}`);
  224. return;
  225. }
  226. // 找到对应的武器节点
  227. const weaponNodeIndex = this.weaponNodes.findIndex(node => node.name === `WeaponNode_${weaponId}`);
  228. if (weaponNodeIndex === -1) {
  229. console.warn(`未找到武器节点: ${weaponId}`);
  230. return;
  231. }
  232. const oldNode = this.weaponNodes[weaponNodeIndex];
  233. const isUnlocked = this.saveDataManager.isWeaponUnlocked(weaponId);
  234. const weaponData = this.saveDataManager.getWeapon(weaponId);
  235. // 创建新节点
  236. let newNode: Node = null;
  237. if (isUnlocked) {
  238. if (this.unlockedWeaponPrefab) {
  239. newNode = instantiate(this.unlockedWeaponPrefab);
  240. await this.setupUnlockedWeaponNode(newNode, weaponConfig, weaponData);
  241. }
  242. } else {
  243. if (this.lockedWeaponPrefab) {
  244. newNode = instantiate(this.lockedWeaponPrefab);
  245. this.setupLockedWeaponNode(newNode, weaponConfig);
  246. }
  247. }
  248. if (newNode) {
  249. newNode.name = `WeaponNode_${weaponId}`;
  250. // 获取旧节点的位置
  251. const siblingIndex = oldNode.getSiblingIndex();
  252. // 移除旧节点
  253. oldNode.removeFromParent();
  254. // 添加新节点到相同位置
  255. this.weaponLayout.node.insertChild(newNode, siblingIndex);
  256. // 更新节点数组
  257. this.weaponNodes[weaponNodeIndex] = newNode;
  258. console.log(`武器 ${weaponId} 状态切换完成: ${isUnlocked ? '解锁' : '锁定'}`);
  259. }
  260. }
  261. /**
  262. * 清除武器节点
  263. */
  264. private clearWeaponNodes() {
  265. this.weaponNodes.forEach(node => {
  266. if (node && node.isValid) {
  267. node.destroy();
  268. }
  269. });
  270. this.weaponNodes = [];
  271. }
  272. /**
  273. * 创建武器节点
  274. */
  275. private async createWeaponNode(weaponConfig: WeaponConfig, index: number) {
  276. // 获取武器数据
  277. const weaponData = this.saveDataManager.getWeapon(weaponConfig.id);
  278. const isUnlocked = this.saveDataManager.isWeaponUnlocked(weaponConfig.id);
  279. console.log(`设置武器节点 ${index}: ${weaponConfig.name}, 等级: ${weaponData?.level || 0}, 已解锁: ${isUnlocked}`);
  280. // 根据解锁状态选择合适的预制体
  281. let weaponNode: Node = null;
  282. if (isUnlocked) {
  283. if (this.unlockedWeaponPrefab) {
  284. weaponNode = instantiate(this.unlockedWeaponPrefab);
  285. await this.setupUnlockedWeaponNode(weaponNode, weaponConfig, weaponData);
  286. }
  287. } else {
  288. if (this.lockedWeaponPrefab) {
  289. weaponNode = instantiate(this.lockedWeaponPrefab);
  290. this.setupLockedWeaponNode(weaponNode, weaponConfig);
  291. }
  292. }
  293. // 如果没有预制体,记录警告
  294. if (!weaponNode) {
  295. console.warn(`无法创建武器节点 ${weaponConfig.name}: 缺少对应的预制体`);
  296. return;
  297. }
  298. // 设置节点名称
  299. weaponNode.name = `WeaponNode_${weaponConfig.id}`;
  300. // 添加到布局中
  301. this.weaponLayout.node.addChild(weaponNode);
  302. this.weaponNodes.push(weaponNode);
  303. }
  304. /**
  305. * 加载武器图标
  306. */
  307. private async loadWeaponSprite(sprite: Sprite, spritePath: string) {
  308. // 转换路径格式,去除"images/"前缀
  309. const bundlePath = spritePath.replace(/^images\//, '');
  310. try {
  311. // 使用BundleLoader从images Bundle加载SpriteFrame
  312. const spriteFrame = await this.bundleLoader.loadSpriteFrame('images', bundlePath);
  313. if (spriteFrame && sprite && sprite.isValid) {
  314. sprite.spriteFrame = spriteFrame;
  315. console.log(`武器图标加载成功: ${spritePath}`);
  316. }
  317. } catch (err) {
  318. console.warn(`加载武器图标失败: ${spritePath}`, err);
  319. }
  320. }
  321. /**
  322. * 设置已解锁武器节点(适配Unlock.prefab)
  323. */
  324. private async setupUnlockedWeaponNode(weaponNode: Node, weaponConfig: WeaponConfig, weaponData: any) {
  325. // 获取公共的Sprite节点,避免重复查找
  326. const spriteNode = weaponNode.getChildByName('Sprite');
  327. if (!spriteNode) {
  328. console.warn('未找到Sprite节点:', weaponConfig.id);
  329. return;
  330. }
  331. // 设置武器图标 - 查找专门的武器图标Sprite节点,避免影响背景
  332. const weaponSprite = spriteNode.getChildByName('WeaponSprite')?.getComponent(Sprite);
  333. if (weaponSprite && weaponConfig.visualConfig.weaponSprites) {
  334. let spritePath: string;
  335. // 检查weaponSprites是字符串还是对象
  336. if (typeof weaponConfig.visualConfig.weaponSprites === 'string') {
  337. spritePath = weaponConfig.visualConfig.weaponSprites;
  338. } else {
  339. // 如果是对象,按优先级选择路径
  340. spritePath = weaponConfig.visualConfig.weaponSprites['I'] ||
  341. weaponConfig.visualConfig.weaponSprites['H-I'] ||
  342. weaponConfig.visualConfig.weaponSprites['L'] ||
  343. weaponConfig.visualConfig.weaponSprites['S'] ||
  344. weaponConfig.visualConfig.weaponSprites['D-T'];
  345. }
  346. if (spritePath) {
  347. await this.loadWeaponSprite(weaponSprite, spritePath);
  348. }
  349. }
  350. // 设置武器名称 - Unlock.prefab中的Name节点下的Label(只显示武器名称)
  351. const nameLabel = spriteNode.getChildByName('Name')?.getComponent(Label);
  352. if (nameLabel) {
  353. nameLabel.string = weaponConfig.name;
  354. }
  355. // 设置武器等级 - should_hide_in_hierarchy/Unlock/Sprite/Level/Label节点(显示等级)
  356. const levelNode = spriteNode.getChildByName('Level');
  357. console.log(`[PreviewInEditor] 处理武器等级显示: ${weaponConfig.name}, weaponData:`, weaponData);
  358. if (levelNode) {
  359. // 先尝试Level节点本身的Label组件
  360. let levelLabel = levelNode.getComponent(Label);
  361. if (!levelLabel) {
  362. // 如果Level节点本身没有Label,尝试查找子节点Label
  363. const labelNode = levelNode.getChildByName('Label');
  364. if (labelNode) {
  365. levelLabel = labelNode.getComponent(Label);
  366. }
  367. }
  368. if (levelLabel) {
  369. const actualLevel = weaponData ? weaponData.level : 0;
  370. levelLabel.string = `${actualLevel}`;
  371. } else {
  372. console.warn(`[PreviewInEditor] 未找到Level Label组件: ${weaponConfig.name}`);
  373. }
  374. } else {
  375. console.warn(`[PreviewInEditor] 未找到Level节点: ${weaponConfig.name}`);
  376. }
  377. // 设置升级按钮 - Unlock.prefab中的Button节点
  378. const upgradeButton = weaponNode.getChildByName('Upgrade')?.getComponent(Button);
  379. if (upgradeButton) {
  380. // 清除之前的事件监听
  381. upgradeButton.node.off(Button.EventType.CLICK);
  382. // 添加升级事件
  383. upgradeButton.node.on(Button.EventType.CLICK, () => {
  384. this.openUpgradePanel(weaponConfig.id);
  385. }, this);
  386. // 设置按钮文本和状态
  387. const buttonLabel = upgradeButton.node.getChildByName('Label')?.getComponent(Label);
  388. if (buttonLabel) {
  389. const maxLevel = weaponConfig.upgradeConfig?.maxLevel || 10;
  390. if (weaponData && weaponData.level >= maxLevel) {
  391. buttonLabel.string = '已满级';
  392. } else {
  393. // 只显示"升级",不显示费用,费用在升级面板中显示
  394. buttonLabel.string = '升 级';
  395. }
  396. }
  397. }
  398. // Unlock.prefab已经有正常的视觉效果,确保节点激活
  399. weaponNode.active = true;
  400. }
  401. /**
  402. * 设置未解锁武器节点(适配Lock.prefab)
  403. */
  404. private setupLockedWeaponNode(weaponNode: Node, weaponConfig: WeaponConfig) {
  405. // 设置解锁信息文本 - Lock.prefab中的Label节点
  406. const unlockLabel = weaponNode.getChildByName('Label')?.getComponent(Label);
  407. if (unlockLabel) {
  408. const unlockLevel = this.getWeaponUnlockLevel(weaponConfig.name);
  409. unlockLabel.string = `通关第${unlockLevel}关解锁`;
  410. }
  411. // Lock.prefab已经有合适的视觉效果,不需要额外设置透明度
  412. weaponNode.active = true;
  413. // 锁定武器节点保持可点击状态以显示解锁提示
  414. // 添加点击事件监听(显示解锁提示)
  415. weaponNode.on(Node.EventType.TOUCH_END, () => {
  416. const unlockLevel = this.getWeaponUnlockLevel(weaponConfig.name);
  417. console.log(`${weaponConfig.name} 需要通关第${unlockLevel}关才能解锁`);
  418. }, this);
  419. }
  420. /**
  421. * 打开升级面板
  422. */
  423. private async openUpgradePanel(weaponId: string) {
  424. const weaponConfig = this.weaponsConfig.weapons.find(config => config.id === weaponId);
  425. if (!weaponConfig) {
  426. console.error(`未找到武器配置: ${weaponId}`);
  427. return;
  428. }
  429. const weaponData = this.saveDataManager.getWeapon(weaponId);
  430. if (!weaponData) {
  431. console.error(`未找到武器数据: ${weaponId}`);
  432. return;
  433. }
  434. this.currentSelectedWeapon = weaponId;
  435. console.log(`打开升级面板: ${weaponConfig.name}, 当前等级: ${weaponData.level}`);
  436. // 刷新面板内容
  437. this.refreshUpgradePanel();
  438. // 使用动画显示升级面板
  439. if (this.upgradeAni) {
  440. await this.upgradeAni.showPanel();
  441. } else {
  442. // 如果没有动画组件,直接显示
  443. this.upgradePanel.active = true;
  444. }
  445. }
  446. /**
  447. * 关闭升级面板
  448. */
  449. private async closeUpgradePanel() {
  450. // 使用动画隐藏升级面板
  451. if (this.upgradeAni) {
  452. await this.upgradeAni.hidePanel();
  453. } else {
  454. // 如果没有动画组件,直接隐藏
  455. this.upgradePanel.active = false;
  456. }
  457. this.currentSelectedWeapon = null;
  458. }
  459. /**
  460. * 刷新升级面板
  461. */
  462. private refreshUpgradePanel() {
  463. if (!this.currentSelectedWeapon || !this.weaponsConfig) return;
  464. const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === this.currentSelectedWeapon);
  465. const weaponData = this.saveDataManager.getWeapon(this.currentSelectedWeapon);
  466. if (!weaponConfig || !weaponData) {
  467. console.error(`刷新升级面板失败: 武器配置或数据不存在 ${this.currentSelectedWeapon}`);
  468. return;
  469. }
  470. console.log(`刷新升级面板: ${weaponConfig.name}, 等级: ${weaponData.level}`);
  471. // 设置武器图标 - Canvas/UpgradeUI/UpgradePanel/WeaponSprite
  472. if (this.panelWeaponSprite && weaponConfig.visualConfig.weaponSprites) {
  473. let spritePath: string;
  474. // 检查weaponSprites是字符串还是对象
  475. if (typeof weaponConfig.visualConfig.weaponSprites === 'string') {
  476. spritePath = weaponConfig.visualConfig.weaponSprites;
  477. } else {
  478. // 如果是对象,按优先级选择路径
  479. spritePath = weaponConfig.visualConfig.weaponSprites['I'] ||
  480. weaponConfig.visualConfig.weaponSprites['H-I'] ||
  481. weaponConfig.visualConfig.weaponSprites['L'] ||
  482. weaponConfig.visualConfig.weaponSprites['S'] ||
  483. weaponConfig.visualConfig.weaponSprites['D-T'];
  484. }
  485. if (spritePath) {
  486. this.loadWeaponSprite(this.panelWeaponSprite, spritePath);
  487. }
  488. }
  489. // 设置武器名称和等级 - Canvas/UpgradeUI/UpgradePanel/LevelLabel
  490. if (this.panelLevelLabel) {
  491. this.panelLevelLabel.string = `${weaponConfig.name} 等级 ${weaponData.level}`;
  492. }
  493. // 计算当前伤害(基础伤害 + 等级加成)- Canvas/UpgradeUI/UpgradePanel/NumberBack/CurrentDamage
  494. const baseDamage = weaponConfig.stats.damage;
  495. const currentDamage = this.calculateWeaponDamage(baseDamage, weaponData.level, this.currentSelectedWeapon);
  496. const nextLevelDamage = this.calculateWeaponDamage(baseDamage, weaponData.level + 1, this.currentSelectedWeapon);
  497. const damageIncrease = nextLevelDamage - currentDamage;
  498. if (this.panelCurrentDamage) {
  499. // 只显示当前伤害数值,不显示增量
  500. this.panelCurrentDamage.string = currentDamage.toString();
  501. }
  502. // 同时更新UpgradeAni组件中的伤害显示
  503. if (this.weaponUpgradeAni && this.weaponUpgradeAni.currentDamageLabel) {
  504. this.weaponUpgradeAni.updateCurrentDamageDisplay(this.currentSelectedWeapon, weaponData.level);
  505. }
  506. // 设置升级费用 - Canvas/UpgradeUI/UpgradePanel/UpgradeBtn/CostLabel
  507. // 优先从武器配置的upgradeConfig字段获取升级费用
  508. let upgradeCost = 0;
  509. const maxLevel = weaponConfig.upgradeConfig?.maxLevel || 10;
  510. if (weaponData.level >= maxLevel) {
  511. // 已达到最大等级,显示"已满级"
  512. if (this.panelCostLabel) {
  513. this.panelCostLabel.string = "已满级";
  514. }
  515. } else {
  516. // 从upgradeConfig获取升级费用
  517. if (weaponConfig.upgradeConfig?.levels) {
  518. const levelConfig = weaponConfig.upgradeConfig.levels[weaponData.level.toString()];
  519. if (levelConfig && levelConfig.cost) {
  520. upgradeCost = levelConfig.cost;
  521. } else {
  522. // 如果upgradeConfig中没有对应等级的费用,使用SaveDataManager的计算方法作为后备
  523. upgradeCost = this.saveDataManager.getWeaponUpgradeCost(this.currentSelectedWeapon);
  524. }
  525. } else {
  526. // 如果没有upgradeConfig,使用SaveDataManager的计算方法
  527. upgradeCost = this.saveDataManager.getWeaponUpgradeCost(this.currentSelectedWeapon);
  528. }
  529. if (this.panelCostLabel) {
  530. // 将数字转换为字符串,并在每个数字之间添加空格
  531. const costString = upgradeCost.toString();
  532. const spacedCostString = costString.split('').join(' ');
  533. this.panelCostLabel.string = spacedCostString;
  534. }
  535. }
  536. // 升级按钮始终保持可点击状态,通过Toast显示各种提示
  537. console.log(`[UpgradeController] 升级按钮保持可交互状态`);
  538. // 检查并更新升级按钮闪烁状态
  539. this.updateUpgradeBtnBlinkState();
  540. }
  541. /**
  542. * 计算武器伤害
  543. */
  544. private calculateWeaponDamage(baseDamage: number, level: number, weaponId?: string): number {
  545. if (level === 0) return 0; // 未解锁武器伤害为0
  546. // 优先从武器配置的upgradeConfig中获取伤害值
  547. if (weaponId && this.weaponsConfig && this.weaponsConfig.weapons) {
  548. const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === weaponId);
  549. if (weaponConfig && weaponConfig.upgradeConfig && weaponConfig.upgradeConfig.levels) {
  550. const levelConfig = weaponConfig.upgradeConfig.levels[level.toString()];
  551. if (levelConfig && typeof levelConfig.damage === 'number') {
  552. console.log(`[UpgradeController] 从upgradeConfig获取伤害: ${weaponId} 等级${level} 伤害${levelConfig.damage}`);
  553. return levelConfig.damage;
  554. }
  555. }
  556. // 如果upgradeConfig中没有伤害值,使用基础伤害 + 等级加成作为后备
  557. if (weaponConfig && weaponConfig.stats && weaponConfig.stats.damage) {
  558. const damage = baseDamage + (level - 1);
  559. console.log(`[UpgradeController] 使用基础伤害计算: ${weaponId} 等级${level} 伤害${damage}`);
  560. return damage;
  561. }
  562. }
  563. // 如果配置不存在,使用默认公式作为最后后备
  564. return baseDamage + (level - 1);
  565. }
  566. /**
  567. * 根据武器名称查找解锁关卡
  568. */
  569. private getWeaponUnlockLevel(weaponName: string): number {
  570. // 武器名称到解锁关卡的映射
  571. const weaponUnlockMap: { [key: string]: number } = {
  572. "毛豆射手": 1,
  573. "尖胡萝卜": 2,
  574. "锯齿草": 3,
  575. "西瓜炸弹": 4,
  576. "回旋镖盆栽": 5,
  577. "炙热辣椒": 6,
  578. "仙人散弹": 7,
  579. "秋葵导弹": 8,
  580. "狼牙棒": 9
  581. };
  582. return weaponUnlockMap[weaponName] || 1;
  583. }
  584. /**
  585. * 根据武器ID查找解锁关卡
  586. */
  587. private getWeaponUnlockLevelById(weaponId: string): number {
  588. // 武器ID到解锁关卡的映射
  589. const weaponUnlockMap: { [key: string]: number } = {
  590. "pea_shooter": 1,
  591. "sharp_carrot": 2,
  592. "saw_grass": 3,
  593. "watermelon_bomb": 4,
  594. "boomerang_plant": 5,
  595. "hot_pepper": 6,
  596. "cactus_shotgun": 7,
  597. "okra_missile": 8,
  598. "mace_club": 9
  599. };
  600. return weaponUnlockMap[weaponId] || 1;
  601. }
  602. /**
  603. * 升级武器
  604. */
  605. private async onUpgradeWeapon() {
  606. console.log(`[UpgradeController] onUpgradeWeapon方法被调用`);
  607. if (!this.currentSelectedWeapon) {
  608. console.log(`[UpgradeController] currentSelectedWeapon为空,退出`);
  609. return;
  610. }
  611. console.log(`[UpgradeController] 开始升级武器: ${this.currentSelectedWeapon}`);
  612. // 检查升级条件并显示相应提示
  613. const weapon = this.saveDataManager.getWeapon(this.currentSelectedWeapon);
  614. console.log(`[UpgradeController] 获取到的武器数据:`, weapon);
  615. if (!weapon) {
  616. console.log(`[UpgradeController] 武器不存在: ${this.currentSelectedWeapon}`);
  617. EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "武器不存在", duration: 2.0 });
  618. return;
  619. }
  620. console.log(`[UpgradeController] 武器等级: ${weapon.level}`);
  621. if (weapon.level === 0) {
  622. console.log(`[UpgradeController] 武器未解锁: ${this.currentSelectedWeapon}`);
  623. EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "请先解锁武器", duration: 2.0 });
  624. return;
  625. }
  626. // 检查是否已达到最大等级
  627. const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === this.currentSelectedWeapon);
  628. const maxLevel = weaponConfig?.upgradeConfig?.maxLevel || 10;
  629. if (weapon.level >= maxLevel) {
  630. console.log(`[UpgradeController] 武器已达到最大等级: ${this.currentSelectedWeapon}`);
  631. EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "武器已达到最大等级", duration: 2.0 });
  632. return;
  633. }
  634. const cost = this.saveDataManager.getWeaponUpgradeCost(this.currentSelectedWeapon);
  635. const playerMoney = this.saveDataManager.getMoney();
  636. console.log(`[UpgradeController] 升级检查 - 武器: ${this.currentSelectedWeapon}, 费用: ${cost}, 当前金币: ${playerMoney}`);
  637. console.log(`[UpgradeController] 费用类型: ${typeof cost}, 金币类型: ${typeof playerMoney}`);
  638. console.log(`[UpgradeController] 条件判断: ${playerMoney} < ${cost} = ${playerMoney < cost}`);
  639. if (playerMoney < cost) {
  640. console.log(`[UpgradeController] 金币不足 - 需要: ${cost}, 当前: ${playerMoney}`);
  641. EventBus.getInstance().emit(GameEvents.SHOW_RESOURCE_TOAST, { message: `金币不足,需要${cost}金币`, duration: 2.0 });
  642. return;
  643. }
  644. console.log(`[UpgradeController] 金币充足,继续升级流程`);
  645. // 记录升级前的金币数量
  646. const coinsBeforeUpgrade = this.saveDataManager.getMoney();
  647. console.log(`[UpgradeController] 升级前金币: ${coinsBeforeUpgrade}`);
  648. const success = this.saveDataManager.upgradeWeapon(this.currentSelectedWeapon);
  649. if (success) {
  650. const coinsAfterUpgrade = this.saveDataManager.getMoney();
  651. console.log(`[UpgradeController] 武器 ${this.currentSelectedWeapon} 升级成功`);
  652. console.log(`[UpgradeController] 升级后金币: ${coinsAfterUpgrade}, 消耗: ${coinsBeforeUpgrade - coinsAfterUpgrade}`);
  653. // 播放武器升级成功动画
  654. this.playWeaponUpgradeSuccessAnimation();
  655. // 刷新升级面板
  656. this.refreshUpgradePanel();
  657. // 更新UpgradeAni组件中的伤害显示
  658. if (this.weaponUpgradeAni && this.weaponUpgradeAni.currentDamageLabel) {
  659. const upgradedWeapon = this.saveDataManager.getWeapon(this.currentSelectedWeapon);
  660. if (upgradedWeapon) {
  661. this.weaponUpgradeAni.updateCurrentDamageDisplay(this.currentSelectedWeapon, upgradedWeapon.level);
  662. console.log(`[UpgradeController] 升级后更新UpgradeAni伤害显示: ${this.currentSelectedWeapon} 等级${upgradedWeapon.level}`);
  663. }
  664. }
  665. // 使用新的状态切换方法更新武器节点
  666. await this.switchWeaponNodeState(this.currentSelectedWeapon);
  667. // 更新升级按钮闪烁状态(升级后钞票可能不足继续升级)
  668. this.updateUpgradeBtnBlinkState();
  669. // 保存数据
  670. this.saveDataManager.savePlayerData();
  671. } else {
  672. console.log(`[UpgradeController] 武器 ${this.currentSelectedWeapon} 升级失败`);
  673. EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: "升级失败,请重试", duration: 1.0 });
  674. // 升级失败时不更新UI
  675. }
  676. }
  677. /**
  678. * 播放武器升级成功动画
  679. */
  680. private async playWeaponUpgradeSuccessAnimation(): Promise<void> {
  681. if (!this.weaponUpgradeAni || !this.panelWeaponSprite) {
  682. console.warn('[UpgradeController] weaponUpgradeAni 或 panelWeaponSprite 未设置,跳过升级动画');
  683. return;
  684. }
  685. try {
  686. // 获取武器图标节点
  687. const weaponIconNode = this.panelWeaponSprite.node;
  688. // 播放升级动画
  689. await this.weaponUpgradeAni.playWeaponUpgradeAnimation(weaponIconNode);
  690. console.log('[UpgradeController] 武器升级动画播放完成');
  691. } catch (error) {
  692. console.error('[UpgradeController] 播放武器升级动画时出错:', error);
  693. }
  694. }
  695. /**
  696. * 解锁武器
  697. */
  698. public async unlockWeapon(weaponId: string): Promise<boolean> {
  699. const success = this.saveDataManager.unlockWeapon(weaponId);
  700. if (success) {
  701. console.log(`武器 ${weaponId} 解锁成功`);
  702. // 使用新的状态切换方法更新武器节点
  703. await this.switchWeaponNodeState(weaponId);
  704. // 保存数据
  705. this.saveDataManager.savePlayerData();
  706. }
  707. return success;
  708. }
  709. /**
  710. * 获取武器当前伤害
  711. */
  712. public getWeaponDamage(weaponId: string): number {
  713. if (!this.weaponsConfig) return 0;
  714. const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === weaponId);
  715. const weaponData = this.saveDataManager.getWeapon(weaponId);
  716. if (!weaponConfig || !weaponData) return 0;
  717. return this.calculateWeaponDamage(weaponConfig.stats.damage, weaponData.level, weaponId);
  718. }
  719. /**
  720. * 刷新UI
  721. */
  722. public async refreshUI() {
  723. await this.refreshWeaponList();
  724. }
  725. /**
  726. * 处理关卡完成事件,自动解锁相应武器
  727. */
  728. private async onLevelComplete() {
  729. if (!this.saveDataManager || !this.weaponsConfig) return;
  730. // 获取当前关卡数据
  731. const currentLevel = this.saveDataManager.getCurrentLevel();
  732. const maxUnlockedLevel = this.saveDataManager.getMaxUnlockedLevel();
  733. const playerData = this.saveDataManager.getPlayerData();
  734. console.log(`[UpgradeController] 关卡完成事件触发`);
  735. console.log(`[UpgradeController] 当前关卡: ${currentLevel}, 最大解锁关卡: ${maxUnlockedLevel}`);
  736. console.log(`[UpgradeController] 玩家数据:`, {
  737. coins: playerData?.money || 0,
  738. currentLevel: playerData?.currentLevel || 1,
  739. maxUnlockedLevel: playerData?.maxUnlockedLevel || 1
  740. });
  741. // 遍历所有武器,检查是否有新解锁的武器
  742. let hasNewUnlocks = false;
  743. const newlyUnlockedWeapons: string[] = [];
  744. for (const weaponConfig of this.weaponsConfig.weapons) {
  745. const weaponId = weaponConfig.id;
  746. const weaponData = this.saveDataManager.getWeapon(weaponId);
  747. const requiredLevel = this.getWeaponUnlockLevelById(weaponId);
  748. // 检查武器是否应该根据关卡进度解锁
  749. const shouldBeUnlocked = maxUnlockedLevel >= requiredLevel;
  750. const isCurrentlyUnlocked = weaponData && weaponData.level > 0;
  751. console.log(`[UpgradeController] 武器检查: ${weaponConfig.name} (${weaponId})`);
  752. console.log(` - 需要关卡: ${requiredLevel}, 当前最大解锁: ${maxUnlockedLevel}`);
  753. console.log(` - 应该解锁: ${shouldBeUnlocked}, 当前已解锁: ${isCurrentlyUnlocked}`);
  754. console.log(` - 武器数据:`, weaponData);
  755. // 如果武器应该解锁但还未解锁,则自动解锁
  756. if (shouldBeUnlocked && !isCurrentlyUnlocked) {
  757. // 确保武器数据存在
  758. if (!weaponData) {
  759. this.saveDataManager.addWeapon(weaponId, weaponConfig.rarity);
  760. }
  761. // 自动解锁武器(设置为level 1,免费解锁)
  762. const updatedWeaponData = this.saveDataManager.getWeapon(weaponId);
  763. if (updatedWeaponData) {
  764. updatedWeaponData.level = 1;
  765. // 由于WeaponData类型中没有unlockTime属性,暂时注释掉这行
  766. // updatedWeaponData.unlockTime = Date.now();
  767. console.log(`[UpgradeController] 自动解锁武器: ${weaponConfig.name} (${weaponId})`);
  768. newlyUnlockedWeapons.push(weaponConfig.name);
  769. hasNewUnlocks = true;
  770. }
  771. }
  772. }
  773. // 如果有新解锁的武器,刷新UI并保存数据
  774. if (hasNewUnlocks) {
  775. await this.refreshWeaponList();
  776. this.saveDataManager.savePlayerData();
  777. console.log(`[UpgradeController] 关卡完成后解锁了 ${newlyUnlockedWeapons.length} 个武器:`, newlyUnlockedWeapons);
  778. // 可以在这里添加解锁提示UI
  779. this.showWeaponUnlockNotification(newlyUnlockedWeapons);
  780. } else {
  781. console.log(`[UpgradeController] 关卡完成后没有新武器解锁`);
  782. }
  783. }
  784. /**
  785. * 显示武器解锁通知
  786. */
  787. private showWeaponUnlockNotification(weaponNames: string[]) {
  788. if (weaponNames.length === 0) return;
  789. // 这里可以实现解锁通知UI
  790. // 目前先用console输出
  791. console.log(`🎉 恭喜解锁新武器: ${weaponNames.join(', ')}!`);
  792. // TODO: 实现实际的UI通知
  793. // 可以显示一个弹窗或者顶部通知条
  794. }
  795. /**
  796. * 获取当前关卡数据(用于调试和UI显示)
  797. */
  798. public getCurrentLevelData() {
  799. if (!this.saveDataManager) return null;
  800. return {
  801. currentLevel: this.saveDataManager.getCurrentLevel(),
  802. maxUnlockedLevel: this.saveDataManager.getMaxUnlockedLevel(),
  803. coins: this.saveDataManager.getMoney(),
  804. diamonds: this.saveDataManager.getDiamonds(),
  805. wallLevel: this.saveDataManager.getWallLevel()
  806. };
  807. }
  808. /**
  809. * 手动检查并解锁武器(用于调试或特殊情况)
  810. */
  811. public async checkAndUnlockWeapons() {
  812. console.log('[UpgradeController] 手动检查武器解锁状态');
  813. await this.onLevelComplete();
  814. }
  815. /**
  816. * 获取所有武器的解锁状态信息(用于调试和UI显示)
  817. */
  818. public getWeaponUnlockStatus() {
  819. if (!this.saveDataManager || !this.weaponsConfig) {
  820. return { error: '数据管理器或武器配置未初始化' };
  821. }
  822. const maxUnlockedLevel = this.saveDataManager.getMaxUnlockedLevel();
  823. const weaponStatus = [];
  824. for (const weaponConfig of this.weaponsConfig.weapons) {
  825. const weaponId = weaponConfig.id;
  826. const weaponData = this.saveDataManager.getWeapon(weaponId);
  827. const requiredLevel = this.getWeaponUnlockLevelById(weaponId);
  828. const shouldBeUnlocked = maxUnlockedLevel >= requiredLevel;
  829. const isCurrentlyUnlocked = weaponData && weaponData.level > 0;
  830. weaponStatus.push({
  831. id: weaponId,
  832. name: weaponConfig.name,
  833. requiredLevel: requiredLevel,
  834. shouldBeUnlocked: shouldBeUnlocked,
  835. isCurrentlyUnlocked: isCurrentlyUnlocked,
  836. currentLevel: weaponData?.level || 0,
  837. // 由于WeaponData类型中没有unlockTime属性,暂时移除该字段
  838. unlocked: weaponData?.level > 0,
  839. needsUpdate: shouldBeUnlocked && !isCurrentlyUnlocked
  840. });
  841. }
  842. return {
  843. maxUnlockedLevel: maxUnlockedLevel,
  844. weapons: weaponStatus,
  845. summary: {
  846. total: weaponStatus.length,
  847. unlocked: weaponStatus.filter(w => w.isCurrentlyUnlocked).length,
  848. shouldBeUnlocked: weaponStatus.filter(w => w.shouldBeUnlocked).length,
  849. needsUpdate: weaponStatus.filter(w => w.needsUpdate).length
  850. }
  851. };
  852. }
  853. /**
  854. * 强制同步所有武器解锁状态(用于修复数据不一致问题)
  855. */
  856. public async forceSyncWeaponUnlocks() {
  857. if (!this.saveDataManager || !this.weaponsConfig) {
  858. console.error('[UpgradeController] 无法强制同步:数据管理器或武器配置未初始化');
  859. return false;
  860. }
  861. const maxUnlockedLevel = this.saveDataManager.getMaxUnlockedLevel();
  862. let syncCount = 0;
  863. console.log(`[UpgradeController] 开始强制同步武器解锁状态,基于最大解锁关卡: ${maxUnlockedLevel}`);
  864. for (const weaponConfig of this.weaponsConfig.weapons) {
  865. const weaponId = weaponConfig.id;
  866. const weaponData = this.saveDataManager.getWeapon(weaponId);
  867. const requiredLevel = this.getWeaponUnlockLevelById(weaponId);
  868. const shouldBeUnlocked = maxUnlockedLevel >= requiredLevel;
  869. const isCurrentlyUnlocked = weaponData && weaponData.level > 0;
  870. if (shouldBeUnlocked && !isCurrentlyUnlocked && weaponData) {
  871. weaponData.level = 1;
  872. // 由于WeaponData类型中没有unlockTime属性,暂时注释掉这行代码
  873. // weaponData.unlockTime = weaponData.unlockTime || Date.now();
  874. syncCount++;
  875. console.log(`[UpgradeController] 强制解锁武器: ${weaponConfig.name} (${weaponId})`);
  876. }
  877. }
  878. if (syncCount > 0) {
  879. this.saveDataManager.savePlayerData();
  880. await this.refreshWeaponList();
  881. console.log(`[UpgradeController] 强制同步完成,解锁了 ${syncCount} 个武器`);
  882. } else {
  883. console.log(`[UpgradeController] 强制同步完成,没有需要更新的武器`);
  884. }
  885. return syncCount > 0;
  886. }
  887. /**
  888. * 诊断武器解锁问题(用于调试)
  889. */
  890. public diagnoseWeaponUnlockIssue() {
  891. console.log('=== 武器解锁问题诊断 ===');
  892. if (!this.saveDataManager) {
  893. console.error('SaveDataManager未初始化');
  894. return;
  895. }
  896. if (!this.weaponsConfig) {
  897. console.error('武器配置未加载');
  898. return;
  899. }
  900. const currentLevel = this.saveDataManager.getCurrentLevel();
  901. const maxUnlockedLevel = this.saveDataManager.getMaxUnlockedLevel();
  902. const playerData = this.saveDataManager.getPlayerData();
  903. console.log(`当前关卡: ${currentLevel}`);
  904. console.log(`最大解锁关卡: ${maxUnlockedLevel}`);
  905. console.log(`金钱: ${playerData?.money || 0}`);
  906. console.log('\n=== 关卡完成状态 ===');
  907. for (let i = 1; i <= 5; i++) {
  908. const progress = this.saveDataManager.getLevelProgress(i);
  909. const isCompleted = this.saveDataManager.isLevelCompleted(i);
  910. console.log(`关卡${i}: 完成=${isCompleted}, 尝试次数=${progress?.attempts || 0}`);
  911. }
  912. console.log('\n=== 武器解锁状态 ===');
  913. const weaponUnlockMap = {
  914. 'pea_shooter': 1,
  915. 'sharp_carrot': 2,
  916. 'saw_grass': 3,
  917. 'watermelon_bomb': 4,
  918. 'boomerang_plant': 5,
  919. 'hot_pepper': 6,
  920. 'cactus_shotgun': 7,
  921. 'okra_missile': 8,
  922. 'mace_club': 9
  923. };
  924. for (const weaponConfig of this.weaponsConfig.weapons) {
  925. const weaponId = weaponConfig.id;
  926. const weaponData = this.saveDataManager.getWeapon(weaponId);
  927. const requiredLevel = weaponUnlockMap[weaponId] || 1;
  928. const shouldBeUnlocked = maxUnlockedLevel >= requiredLevel;
  929. const isCurrentlyUnlocked = weaponData && weaponData.level > 0;
  930. console.log(`${weaponConfig.name} (${weaponId}):`);
  931. console.log(` 需要关卡: ${requiredLevel}`);
  932. console.log(` 应该解锁: ${shouldBeUnlocked}`);
  933. console.log(` 当前状态: ${isCurrentlyUnlocked ? '已解锁' : '未解锁'}`);
  934. console.log(` 武器等级: ${weaponData?.level || 0}`);
  935. if (shouldBeUnlocked && !isCurrentlyUnlocked) {
  936. console.log(` ❌ 问题:应该解锁但未解锁`);
  937. } else if (shouldBeUnlocked && isCurrentlyUnlocked) {
  938. console.log(` ✅ 正常:已正确解锁`);
  939. } else {
  940. console.log(` ⏳ 等待:尚未达到解锁条件`);
  941. }
  942. }
  943. console.log('\n=== 修复建议 ===');
  944. console.log('如果发现武器解锁状态不正确,请运行以下命令:');
  945. console.log('1. 在控制台运行: window.upgradeController.forceSyncWeaponUnlocks()');
  946. console.log('2. 或者刷新页面重新初始化');
  947. // 将实例暴露到全局,方便调试
  948. (window as any).upgradeController = this;
  949. }
  950. /**
  951. * 货币变化事件处理
  952. */
  953. private onCurrencyChanged() {
  954. console.log('[UpgradeController] 货币发生变化,检查升级按钮闪烁状态');
  955. // 如果升级面板打开,更新闪烁状态
  956. if (this.upgradePanel && this.upgradePanel.active && this.currentSelectedWeapon) {
  957. this.updateUpgradeBtnBlinkState();
  958. }
  959. }
  960. /**
  961. * 更新升级按钮闪烁状态
  962. */
  963. private updateUpgradeBtnBlinkState() {
  964. if (!this.weaponUpgradeAni || !this.currentSelectedWeapon) {
  965. return;
  966. }
  967. const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === this.currentSelectedWeapon);
  968. const weaponData = this.saveDataManager.getWeapon(this.currentSelectedWeapon);
  969. if (!weaponConfig || !weaponData) {
  970. return;
  971. }
  972. const maxLevel = weaponConfig.upgradeConfig?.maxLevel || 10;
  973. // 如果武器已达到最大等级,停止闪烁
  974. if (weaponData.level >= maxLevel) {
  975. this.weaponUpgradeAni.stopUpgradeBtnBlink();
  976. console.log(`[UpgradeController] 武器已满级,停止闪烁: ${this.currentSelectedWeapon}`);
  977. return;
  978. }
  979. // 检查钞票是否足够升级
  980. const canUpgrade = this.saveDataManager.canUpgradeWeapon(this.currentSelectedWeapon);
  981. if (canUpgrade) {
  982. // 钞票足够,开始闪烁
  983. if (!this.weaponUpgradeAni.isUpgradeBtnBlinking()) {
  984. this.weaponUpgradeAni.startUpgradeBtnBlink();
  985. console.log(`[UpgradeController] 钞票足够,开始闪烁: ${this.currentSelectedWeapon}`);
  986. }
  987. } else {
  988. // 钞票不够,停止闪烁
  989. if (this.weaponUpgradeAni.isUpgradeBtnBlinking()) {
  990. this.weaponUpgradeAni.stopUpgradeBtnBlink();
  991. console.log(`[UpgradeController] 钞票不足,停止闪烁: ${this.currentSelectedWeapon}`);
  992. }
  993. }
  994. }
  995. /**
  996. * 组件销毁时清理事件监听
  997. */
  998. onDestroy() {
  999. EventBus.getInstance().off(GameEvents.GAME_SUCCESS, this.onLevelComplete, this);
  1000. EventBus.getInstance().off(GameEvents.CURRENCY_CHANGED, this.onCurrencyChanged, this);
  1001. }
  1002. }