GroundBurnAreaManager.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import { _decorator, Component, Node, Prefab, instantiate, resources, Vec3 } from 'cc';
  2. import { GroundBurnArea } from './GroundBurnArea';
  3. import { HitEffectConfig } from '../../Core/ConfigManager';
  4. import { WeaponBullet } from '../WeaponBullet';
  5. import { PhysicsManager } from '../../Core/PhysicsManager';
  6. const { ccclass, property } = _decorator;
  7. /**
  8. * 地面燃烧区域管理器
  9. * 单例模式,统一管理所有地面燃烧区域的创建和销毁
  10. */
  11. @ccclass('GroundBurnAreaManager')
  12. export class GroundBurnAreaManager extends Component {
  13. private static _instance: GroundBurnAreaManager = null;
  14. @property({
  15. type: Node,
  16. tooltip: '游戏区域节点,燃烧区域将在此节点下创建'
  17. })
  18. public gameArea: Node = null;
  19. @property({
  20. type: Prefab,
  21. tooltip: '地面燃烧区域预制体'
  22. })
  23. public groundBurnAreaPrefab: Prefab = null;
  24. private activeBurnAreas: Node[] = [];
  25. /**
  26. * 组件加载时设置单例
  27. */
  28. protected onLoad(): void {
  29. if (GroundBurnAreaManager._instance === null) {
  30. GroundBurnAreaManager._instance = this;
  31. console.log('[GroundBurnAreaManager] 单例初始化成功');
  32. } else {
  33. console.warn('[GroundBurnAreaManager] 单例已存在,销毁重复实例');
  34. this.node.destroy();
  35. }
  36. }
  37. /**
  38. * 组件启动时验证配置
  39. */
  40. protected start(): void {
  41. if (!this.gameArea) {
  42. console.error('[GroundBurnAreaManager] gameArea未设置,请在Inspector中拖拽GameArea节点');
  43. }
  44. if (!this.groundBurnAreaPrefab) {
  45. console.error('[GroundBurnAreaManager] groundBurnAreaPrefab未设置,请在Inspector中拖拽GroundBurnArea预制体');
  46. }
  47. console.log('[GroundBurnAreaManager] 管理器配置验证完成');
  48. }
  49. onDestroy() {
  50. if (GroundBurnAreaManager._instance === this) {
  51. GroundBurnAreaManager._instance = null;
  52. }
  53. // 清理所有活跃的燃烧区域
  54. this.clearAllBurnAreas();
  55. }
  56. /**
  57. * 获取单例实例
  58. */
  59. public static getInstance(): GroundBurnAreaManager | null {
  60. return GroundBurnAreaManager._instance;
  61. }
  62. /**
  63. * 创建地面燃烧区域
  64. * @param position 燃烧区域位置
  65. * @param effect 效果配置
  66. * @param weaponBullet 武器子弹组件(用于获取最终伤害)
  67. * @param defaultBurnEffectPath 默认燃烧特效路径
  68. */
  69. public createGroundBurnArea(
  70. position: Vec3,
  71. effect: HitEffectConfig,
  72. weaponBullet: WeaponBullet | null,
  73. defaultBurnEffectPath?: string
  74. ): Node | null {
  75. if (!this.groundBurnAreaPrefab) {
  76. console.error('[GroundBurnAreaManager] 地面燃烧区域预制体未设置');
  77. return null;
  78. }
  79. if (!this.gameArea) {
  80. console.error('[GroundBurnAreaManager] 游戏区域节点未设置');
  81. return null;
  82. }
  83. // 检查物理系统状态
  84. const physicsManager = PhysicsManager.getInstance();
  85. if (!physicsManager) {
  86. console.warn('[GroundBurnAreaManager] 物理系统未初始化,无法创建燃烧区域');
  87. return null;
  88. }
  89. const physicsSystem = physicsManager.getSystem();
  90. if (!physicsSystem || !physicsSystem.enable) {
  91. console.warn('[GroundBurnAreaManager] 物理系统未启用,无法创建燃烧区域');
  92. return null;
  93. }
  94. try {
  95. // 实例化预制体
  96. const burnAreaNode = instantiate(this.groundBurnAreaPrefab);
  97. // 添加到游戏区域
  98. this.gameArea.addChild(burnAreaNode);
  99. // 获取地面燃烧区域组件
  100. const groundBurnArea = burnAreaNode.getComponent(GroundBurnArea);
  101. if (!groundBurnArea) {
  102. console.error('[GroundBurnAreaManager] 预制体中未找到 GroundBurnArea 组件');
  103. burnAreaNode.destroy();
  104. return null;
  105. }
  106. // 计算燃烧伤害:DPS = (effect.damage 或 5) + 武器等级;每次伤害 = DPS * tickInterval
  107. const weaponId = weaponBullet?.getWeaponConfig()?.id || 'unknown';
  108. const weaponLevel = weaponBullet?.getWeaponInfo()?.getWeaponLevel?.() ?? 1;
  109. const baseDps = (typeof effect.damage === 'number' ? effect.damage : 5);
  110. const tickInterval = (typeof effect.tickInterval === 'number' ? effect.tickInterval : 0.5);
  111. const burnDps = baseDps + weaponLevel;
  112. const perTickDamage = Math.max(0, burnDps * tickInterval);
  113. console.log(`[GroundBurnAreaManager] 计算燃烧伤害: weapon=${weaponId}, level=${weaponLevel}, baseDPS=${baseDps}, tick=${tickInterval}, DPS=${burnDps}, perTick=${perTickDamage.toFixed(2)}`);
  114. // 初始化燃烧区域
  115. groundBurnArea.initGroundBurnArea(
  116. position,
  117. effect.duration || 3,
  118. perTickDamage,
  119. tickInterval
  120. );
  121. // 添加到活跃列表
  122. this.activeBurnAreas.push(burnAreaNode);
  123. console.log(`[GroundBurnAreaManager] 地面燃烧区域已创建,位置: (${position.x.toFixed(1)}, ${position.y.toFixed(1)})`);
  124. return burnAreaNode;
  125. } catch (error) {
  126. console.error('[GroundBurnAreaManager] 创建地面燃烧区域失败:', error);
  127. return null;
  128. }
  129. }
  130. /**
  131. * 移除燃烧区域
  132. */
  133. public removeBurnArea(burnAreaNode: Node) {
  134. const index = this.activeBurnAreas.indexOf(burnAreaNode);
  135. if (index !== -1) {
  136. this.activeBurnAreas.splice(index, 1);
  137. console.log(`[GroundBurnAreaManager] 燃烧区域已从活跃列表中移除`);
  138. }
  139. }
  140. /**
  141. * 清理所有燃烧区域
  142. */
  143. public clearAllBurnAreas() {
  144. console.log(`[GroundBurnAreaManager] 清理所有燃烧区域,数量: ${this.activeBurnAreas.length}`);
  145. for (const burnArea of this.activeBurnAreas) {
  146. if (burnArea && burnArea.isValid) {
  147. const groundBurnArea = burnArea.getComponent(GroundBurnArea);
  148. if (groundBurnArea) {
  149. groundBurnArea.destroyBurnArea();
  150. } else {
  151. burnArea.destroy();
  152. }
  153. }
  154. }
  155. this.activeBurnAreas = [];
  156. }
  157. /**
  158. * 获取活跃燃烧区域数量
  159. */
  160. public getActiveBurnAreaCount(): number {
  161. return this.activeBurnAreas.length;
  162. }
  163. /**
  164. * 获取所有活跃的燃烧区域
  165. */
  166. public getActiveBurnAreas(): Node[] {
  167. return [...this.activeBurnAreas];
  168. }
  169. }