import { _decorator, Component, Node, Label, find, JsonAsset } from 'cc'; import { SaveDataManager } from '../LevelSystem/SaveDataManager'; import EventBus, { GameEvents } from '../Core/EventBus'; import { JsonConfigLoader } from '../Core/JsonConfigLoader'; import { SkillManager } from './SkillSelection/SkillManager'; const { ccclass, property } = _decorator; /** * 墙体组件 * 负责管理墙体的血量、伤害处理、等级升级等功能 */ @ccclass('Wall') export class Wall extends Component { @property({ type: Node, tooltip: '血量显示节点 (HeartLabel)' }) public heartLabelNode: Node = null; // @property({ // type: JsonAsset, // tooltip: '墙体配置文件' // }) // public wallConfigAsset: JsonAsset = null; // 已改为动态加载 // === 私有属性 === private currentHealth: number = 100; private heartLabel: Label = null; private saveDataManager: SaveDataManager = null; // 墙体配置数据 private wallConfig: any = null; private wallHpMap: Record = {}; async start() { await this.initializeWall(); } /** * 加载墙体配置 */ private async loadWallConfig(): Promise { try { this.wallConfig = await JsonConfigLoader.getInstance().loadConfig('wall'); if (this.wallConfig && this.wallConfig.wallConfig && this.wallConfig.wallConfig.healthByLevel) { // 转换字符串键为数字键 const healthByLevel = this.wallConfig.wallConfig.healthByLevel; this.wallHpMap = {}; for (const level in healthByLevel) { this.wallHpMap[parseInt(level)] = healthByLevel[level]; } console.log('[Wall] 墙体配置加载成功:', this.wallHpMap); } else { console.warn('[Wall] 配置文件格式错误,使用默认配置'); this.useDefaultConfig(); } } catch (error) { console.error('[Wall] 加载wall.json时出错:', error); this.useDefaultConfig(); } } /** * 使用默认配置 */ private useDefaultConfig(): void { this.wallHpMap = { 1: 100, 2: 500, 3: 1200, 4: 1500, 5: 2000 }; } /** * 初始化墙体 */ private async initializeWall() { // 初始化存档管理器 this.saveDataManager = SaveDataManager.getInstance(); if (!this.saveDataManager) { console.error('[Wall] SaveDataManager not found'); return; } // 加载墙体配置 await this.loadWallConfig(); // 查找血量显示节点 this.findHeartLabelNode(); // 从存档读取墙体血量 this.loadWallHealthFromSave(); // 初始化血量显示 this.updateHealthDisplay(); // 监听治疗技能变化 this.setupSkillListeners(); // 设置事件监听器 this.setupEventListeners(); } /** * 查找血量显示节点 */ private findHeartLabelNode() { // 查找心血显示节点 if (!this.heartLabelNode) { this.heartLabelNode = find('Canvas-001/TopArea/HeartNode/HeartLabel') || find('Canvas/GameLevelUI/HeartNode/HeartLabel'); } if (this.heartLabelNode) { this.heartLabel = this.heartLabelNode.getComponent(Label); } } /** * 从存档加载墙体血量 */ private loadWallHealthFromSave() { // 直接从SaveDataManager获取当前墙体血量 this.currentHealth = this.saveDataManager.getWallHealth(); console.log('[Wall] 从配置加载墙体血量:', this.currentHealth); // 确保当前血量不超过最大血量(考虑技能加成) const maxHealth = this.getMaxHealth(); if (this.currentHealth > maxHealth) { this.currentHealth = maxHealth; } } /** * 墙体受到伤害 */ public takeDamage(damage: number) { if (damage <= 0) return; const previousHealth = this.currentHealth; this.currentHealth = Math.max(0, this.currentHealth - damage); // 触发受到伤害事件 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.WALL_TAKE_DAMAGE, { damage: damage, previousHealth: previousHealth, currentHealth: this.currentHealth }); // 触发血量变化事件 eventBus.emit(GameEvents.WALL_HEALTH_CHANGED, { previousHealth: previousHealth, currentHealth: this.currentHealth, maxHealth: this.getMaxHealth() }); // 更新血量显示 this.updateHealthDisplay(); console.log(`[Wall] 墙体受到伤害: ${damage}, 当前血量: ${this.currentHealth}`); // 检查墙体是否被摧毁 if (this.currentHealth <= 0) { this.onWallDestroyed(); } } /** * 墙体被摧毁时的处理 * 统一与菜单退出的失败处理流程,直接触发GAME_DEFEAT事件 */ private onWallDestroyed() { console.log('[Wall] 墙体被摧毁,触发游戏失败'); // 通过事件系统触发墙体被摧毁事件(保留用于其他监听器) const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.WALL_DESTROYED, { finalHealth: this.currentHealth, maxHealth: this.getMaxHealth() }); // 统一失败处理:直接触发GAME_DEFEAT事件,与菜单退出处理保持一致 console.log('[Wall] 直接触发GAME_DEFEAT事件,与菜单退出失败处理流程一致'); eventBus.emit(GameEvents.GAME_DEFEAT); } /** * 更新血量显示 */ public updateHealthDisplay() { if (this.heartLabel) { this.heartLabel.string = Math.floor(this.currentHealth).toString(); } } /** * 设置墙体血量 */ public setHealth(health: number) { const previousHealth = this.currentHealth; this.currentHealth = Math.max(0, health); // 如果血量发生变化,触发血量变化事件 if (previousHealth !== this.currentHealth) { const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.WALL_HEALTH_CHANGED, { previousHealth: previousHealth, currentHealth: this.currentHealth, maxHealth: this.getMaxHealth() }); } this.updateHealthDisplay(); } /** * 获取当前墙体血量 */ public getCurrentHealth(): number { return this.currentHealth; } /** * 获取最大血量(基于当前等级和技能加成) */ public getMaxHealth(): number { const currentLevel = this.getCurrentWallLevel(); const baseMaxHealth = this.getWallHealthByLevel(currentLevel); // 应用治疗技能的最大血量加成 const skillManager = SkillManager.getInstance(); if (skillManager) { const healSkillLevel = skillManager.getSkillLevel('heal'); const healthBonus = SkillManager.getHealSkillHealthBonus(healSkillLevel); return Math.floor(baseMaxHealth * (1 + healthBonus)); } return baseMaxHealth; } /** * 根据等级获取墙体血量 */ public getWallHealthByLevel(level: number): number { // 使用本地配置 return this.wallHpMap[level] || (100 + (level - 1) * 200); } /** * 获取当前墙壁等级 */ public getCurrentWallLevel(): number { return this.saveDataManager?.getWallLevel() || 1; } /** * 恢复墙体血量 */ public heal(amount: number) { const previousHealth = this.currentHealth; const maxHealth = this.getMaxHealth(); this.currentHealth = Math.min(maxHealth, this.currentHealth + amount); // 如果血量发生变化,触发血量变化事件 if (previousHealth !== this.currentHealth) { const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.WALL_HEALTH_CHANGED, { previousHealth: previousHealth, currentHealth: this.currentHealth, maxHealth: maxHealth, healAmount: this.currentHealth - previousHealth }); } this.updateHealthDisplay(); } /** * 重置墙体血量到满血 */ public resetToFullHealth() { this.currentHealth = this.getMaxHealth(); this.updateHealthDisplay(); } /** * 获取血量百分比 */ public getHealthPercentage(): number { const maxHealth = this.getMaxHealth(); return maxHealth > 0 ? this.currentHealth / maxHealth : 0; } /** * 检查墙体是否存活 */ public isAlive(): boolean { return this.currentHealth > 0; } /** * 设置事件监听器 */ private setupEventListeners() { const eventBus = EventBus.getInstance(); // 监听重置墙体血量事件 eventBus.on(GameEvents.RESET_WALL_HEALTH, this.onResetWallHealthEvent, this); // 监听墙体血量变化事件(用于升级后更新显示) eventBus.on(GameEvents.WALL_HEALTH_CHANGED, this.onWallHealthChangedEvent, this); } /** * 处理重置墙体血量事件 */ private onResetWallHealthEvent() { console.log('[Wall] 接收到重置墙体血量事件,重置到满血'); this.resetToFullHealth(); } /** * 处理墙体血量变化事件(用于升级后更新) */ private onWallHealthChangedEvent(eventData?: any) { // 只有在特定情况下才重新加载存档数据,避免覆盖受伤后的血量 // 如果事件数据包含isUpgrade标志,说明是升级触发的,需要重新加载 if (eventData && eventData.isUpgrade) { console.log('[Wall] 接收到墙体升级事件,重新加载血量数据'); this.loadWallHealthFromSave(); this.updateHealthDisplay(); } // 其他情况(如受伤、治疗)不需要重新加载存档,血量已经在相应方法中更新 } /** * 设置技能监听器 */ private setupSkillListeners() { const skillManager = SkillManager.getInstance(); if (skillManager) { // 监听治疗技能变化 skillManager.onSkillChanged('heal', this.onHealSkillChanged.bind(this)); } } /** * 治疗技能变化回调 */ private onHealSkillChanged(skillId: string, level: number) { console.log(`[Wall] 治疗技能等级变化: ${level}`); // 技能升级时,墙体最大血量可能增加,需要更新显示 this.updateHealthDisplay(); // 如果当前血量低于新的最大血量,可以考虑给予一些额外治疗 // 这里暂时不做额外处理,因为SkillSelectionController已经处理了即时治疗 } /** * 清理技能监听器 */ private cleanupSkillListeners() { const skillManager = SkillManager.getInstance(); if (skillManager) { skillManager.offSkillChanged('heal', this.onHealSkillChanged.bind(this)); } } onDestroy() { // 清理事件监听 const eventBus = EventBus.getInstance(); eventBus.off(GameEvents.RESET_WALL_HEALTH, this.onResetWallHealthEvent, this); eventBus.off(GameEvents.WALL_HEALTH_CHANGED, this.onWallHealthChangedEvent, this); this.cleanupSkillListeners(); } }