EnemyComponent.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. import { _decorator, Component, Node, Color, UIOpacity } from 'cc';
  2. import { sp } from 'cc';
  3. import { ConfigManager, EnemyConfig } from '../Core/ConfigManager';
  4. const { ccclass, property } = _decorator;
  5. /**
  6. * 敌人组件
  7. * 用于存储敌人的配置信息和基础属性
  8. */
  9. @ccclass('EnemyComponent')
  10. export class EnemyComponent extends Component {
  11. public enemyConfig: EnemyConfig = null;
  12. public spawner: any = null; // 对生成器的引用
  13. private rageActive: boolean = false;
  14. private rageStartTime: number = 0;
  15. // 隐身状态
  16. private stealthActive: boolean = false;
  17. start() {
  18. // 如果具备隐身能力,则初始化隐身循环
  19. const ability = this.getSpecialAbility();
  20. if (ability === 'stealth') {
  21. const cooldown = this.getSpecialAbilityCooldown();
  22. // 初始进入隐身
  23. this.applyStealthOpacity(100);
  24. this.stealthActive = true;
  25. // 按冷却时间循环切换显隐
  26. this.schedule(() => {
  27. if (this.stealthActive) {
  28. this.applyStealthOpacity(255);
  29. } else {
  30. this.applyStealthOpacity(100);
  31. }
  32. this.stealthActive = !this.stealthActive;
  33. }, Math.max(0.1, cooldown));
  34. }
  35. }
  36. onDisable() {
  37. // 组件禁用时取消调度,避免泄漏
  38. this.unscheduleAllCallbacks();
  39. }
  40. // 获取敌人生命值
  41. public getHealth(): number {
  42. return this.enemyConfig?.stats?.health || 100;
  43. }
  44. // 获取敌人速度
  45. public getSpeed(): number {
  46. return this.enemyConfig?.stats?.speed || 50;
  47. }
  48. // 获取敌人伤害
  49. public getDamage(): number {
  50. return this.enemyConfig?.combat?.attackDamage || 20;
  51. }
  52. // 获取敌人攻击范围
  53. public getAttackRange(): number {
  54. return this.enemyConfig?.combat?.attackRange || 30;
  55. }
  56. // 获取敌人攻击速度
  57. public getAttackSpeed(): number {
  58. return this.enemyConfig?.combat?.attackSpeed || 1.0;
  59. }
  60. // 获取敌人防御力
  61. public getDefense(): number {
  62. return this.enemyConfig?.stats?.defense || 0;
  63. }
  64. // 获取击杀奖励
  65. public getCoinReward(): number {
  66. return this.enemyConfig?.stats?.dropEnergy || 1;
  67. }
  68. // === 移动相关配置 ===
  69. // 获取移动类型
  70. public getMovementType(): string {
  71. return this.enemyConfig?.movement?.moveType || 'straight';
  72. }
  73. // 获取移动模式
  74. public getMovementPattern(): string {
  75. return this.enemyConfig?.movement?.pattern || 'direct';
  76. }
  77. // 获取摆动幅度
  78. public getSwingAmplitude(): number {
  79. return this.enemyConfig?.movement?.swingAmplitude || 0.0;
  80. }
  81. // 获取摆动频率
  82. public getSwingFrequency(): number {
  83. return this.enemyConfig?.movement?.swingFrequency || 0.0;
  84. }
  85. // 获取速度变化
  86. public getSpeedVariation(): number {
  87. return this.enemyConfig?.movement?.speedVariation || 0.1;
  88. }
  89. // 获取旋转速度
  90. public getRotationSpeed(): number {
  91. return this.enemyConfig?.movement?.rotationSpeed || 180.0;
  92. }
  93. // === 战斗相关配置 ===
  94. // 获取攻击类型
  95. public getAttackType(): string {
  96. return this.enemyConfig?.combat?.attackType || 'melee';
  97. }
  98. // 获取攻击冷却时间
  99. public getAttackCooldown(): number {
  100. return this.enemyConfig?.combat?.attackCooldown || 2.0;
  101. }
  102. // 获取攻击延迟
  103. public getAttackDelay(): number {
  104. return this.enemyConfig?.combat?.attackDelay || 1.0;
  105. }
  106. // 获取武器类型
  107. public getWeaponType(): string {
  108. return this.enemyConfig?.combat?.weaponType || 'none';
  109. }
  110. // 获取投掷物类型
  111. public getProjectileType(): string {
  112. return this.enemyConfig?.combat?.projectileType || 'none';
  113. }
  114. // 获取投掷物速度
  115. public getProjectileSpeed(): number {
  116. return this.enemyConfig?.combat?.projectileSpeed || 100.0;
  117. }
  118. // 是否造成墙体震动
  119. public getCausesWallShake(): boolean {
  120. return this.enemyConfig?.combat?.causesWallShake || false;
  121. }
  122. // === 格挡系统 ===
  123. // 是否可以格挡
  124. public canBlock(): boolean {
  125. return this.enemyConfig?.combat?.canBlock || false;
  126. }
  127. // 获取格挡几率
  128. public getBlockChance(): number {
  129. return this.enemyConfig?.combat?.blockChance || 0.0;
  130. }
  131. // 获取格挡伤害减免
  132. public getBlockDamageReduction(): number {
  133. return this.enemyConfig?.combat?.blockDamageReduction || 0.5;
  134. }
  135. // === 狂暴系统 ===
  136. // 是否有狂暴能力
  137. public hasRage(): boolean {
  138. return this.enemyConfig?.boss?.rage_threshold > 0 || false;
  139. }
  140. // 获取狂暴触发血量阈值
  141. public getRageThreshold(): number {
  142. return this.enemyConfig?.boss?.rage_threshold || 0.3;
  143. }
  144. // 获取狂暴触发血量阈值(别名方法)
  145. public getRageTriggerThreshold(): number {
  146. return this.getRageThreshold();
  147. }
  148. // 获取狂暴伤害倍率
  149. public getRageDamageMultiplier(): number {
  150. return this.enemyConfig?.boss?.rage_damage_multiplier || 1.5;
  151. }
  152. // 获取狂暴速度倍率
  153. public getRageSpeedMultiplier(): number {
  154. return this.enemyConfig?.boss?.rage_speed_multiplier || 1.3;
  155. }
  156. // 获取狂暴持续时间
  157. public getRageDuration(): number {
  158. return 10.0; // 固定持续时间
  159. }
  160. // === 特殊能力 ===
  161. // 获取特殊能力类型
  162. public getSpecialAbility(): string {
  163. const abilities = this.enemyConfig?.special_abilities;
  164. if (Array.isArray(abilities) && abilities.length > 0) {
  165. return abilities[0]?.type || 'none';
  166. }
  167. return 'none';
  168. }
  169. // 获取特殊能力冷却时间
  170. public getSpecialAbilityCooldown(): number {
  171. const abilities = this.enemyConfig?.special_abilities;
  172. if (Array.isArray(abilities) && abilities.length > 0) {
  173. const cooldown = abilities[0]?.cooldown;
  174. return typeof cooldown === 'number' ? cooldown : 5.0;
  175. }
  176. return 5.0;
  177. }
  178. /**
  179. * 应用隐身透明度到 EnemySprite 的 Skeleton
  180. * @param opacity 透明度(0-255),示例:50 表示半透明
  181. */
  182. private applyStealthOpacity(opacity: number): void {
  183. const enemySprite = this.findEnemySpriteNode();
  184. if (!enemySprite) {
  185. console.warn('[EnemyComponent] 未找到 EnemySprite 节点,无法应用隐身透明度');
  186. return;
  187. }
  188. // 设置 UIOpacity 以保证整节点透明度生效
  189. let uiOpacity = enemySprite.getComponent(UIOpacity);
  190. if (!uiOpacity) {
  191. uiOpacity = enemySprite.addComponent(UIOpacity);
  192. }
  193. uiOpacity.opacity = Math.max(0, Math.min(255, opacity));
  194. // 同时设置 Skeleton 的颜色 alpha(与编辑器表现一致)
  195. const skeleton = enemySprite.getComponent(sp.Skeleton);
  196. if (skeleton) {
  197. const current = skeleton.color ?? new Color(255, 255, 255, 255);
  198. const next = new Color(current.r, current.g, current.b, Math.max(0, Math.min(255, opacity)));
  199. skeleton.color = next;
  200. }
  201. }
  202. /**
  203. * 在当前节点层级下查找 EnemySprite 节点(兼容不同层级路径)
  204. */
  205. private findEnemySpriteNode(): Node | null {
  206. // 直接子节点命中
  207. const direct = this.node.getChildByName('EnemySprite');
  208. if (direct) return direct;
  209. // 深度遍历查找
  210. const stack: Node[] = [...this.node.children];
  211. while (stack.length > 0) {
  212. const cur = stack.pop()!;
  213. if (cur.name === 'EnemySprite') return cur;
  214. stack.push(...cur.children);
  215. }
  216. return null;
  217. }
  218. // === 狂暴状态管理 ===
  219. // 检查是否处于狂暴状态
  220. public isInRage(): boolean {
  221. if (!this.rageActive) return false;
  222. // 检查狂暴是否过期
  223. const currentTime = Date.now();
  224. const rageDuration = this.getRageDuration() * 1000; // 转换为毫秒
  225. if (currentTime - this.rageStartTime > rageDuration) {
  226. this.endRage();
  227. return false;
  228. }
  229. return true;
  230. }
  231. // 触发狂暴状态
  232. public triggerRage(): void {
  233. if (!this.hasRage()) return;
  234. this.rageActive = true;
  235. this.rageStartTime = Date.now();
  236. console.log(`[EnemyComponent] 狂暴状态激活,持续时间: ${this.getRageDuration()}秒`);
  237. }
  238. // 结束狂暴状态
  239. public endRage(): void {
  240. this.rageActive = false;
  241. this.rageStartTime = 0;
  242. console.log(`[EnemyComponent] 狂暴状态结束`);
  243. }
  244. // 获取当前攻击力(考虑狂暴加成)
  245. public getCurrentAttackPower(): number {
  246. const baseDamage = this.getDamage();
  247. if (this.isInRage()) {
  248. return baseDamage * this.getRageDamageMultiplier();
  249. }
  250. return baseDamage;
  251. }
  252. // 获取当前移动速度(考虑狂暴加成)
  253. public getCurrentSpeed(): number {
  254. const baseSpeed = this.getSpeed();
  255. if (this.isInRage()) {
  256. return baseSpeed * this.getRageSpeedMultiplier();
  257. }
  258. return baseSpeed;
  259. }
  260. // 获取动画配置
  261. public getAnimations(): any {
  262. return this.enemyConfig?.visualConfig?.animations || {};
  263. }
  264. // 获取音频配置
  265. public getAudioConfig(): any {
  266. return this.enemyConfig?.audioConfig || {};
  267. }
  268. // 检查是否有特殊能力
  269. public hasSpecialAbility(abilityType: string): boolean {
  270. if (!this.enemyConfig || !this.enemyConfig.special_abilities) return false;
  271. return this.enemyConfig.special_abilities.some(ability => ability.type === abilityType);
  272. }
  273. // 获取特殊配置
  274. public getBossConfig(): any {
  275. return this.enemyConfig?.boss || null;
  276. }
  277. // 获取敌人信息文本
  278. public getEnemyInfo(): string {
  279. if (!this.enemyConfig) return '未知敌人';
  280. return `${this.enemyConfig.name}\n` +
  281. `类型: ${this.enemyConfig.type}\n` +
  282. `生命值: ${this.enemyConfig.stats?.health || 0}\n` +
  283. `速度: ${this.enemyConfig.stats?.speed || 0}\n` +
  284. `伤害: ${this.enemyConfig.combat?.attackDamage || 0}\n` +
  285. `攻击范围: ${this.enemyConfig.combat?.attackRange || 0}`;
  286. }
  287. // 死亡时调用
  288. public onDeath() {
  289. if (this.spawner && this.spawner.onEnemyDeath) {
  290. this.spawner.onEnemyDeath(this.node);
  291. }
  292. }
  293. }