SysSkill.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /** @format */
  2. import {ComRole} from '../components/ComRole'
  3. import {ECSSystem} from '../lib/ECSSystem'
  4. import {GenFilterKey} from '../lib/ECSComponent'
  5. import {FightWorld} from '../worlds/FightWorld'
  6. import {ComCocosNode} from '../components/ComCocosNode'
  7. import {ComSkill} from '../components/ComSkill'
  8. import {cCollider} from '../../collision/Collider'
  9. import {ComTransform} from '../components/ComTransform'
  10. import {Log} from '../../utils/LogUtils'
  11. import {
  12. BUFF_EFFECT_TYPE,
  13. BUFF_TYPE,
  14. HIT_ANI_TYPE,
  15. NEGATIVE_TYPE,
  16. ROLE_TYPE,
  17. SKILL_DIR_TYPE,
  18. SKILL_EFFECT_TYPE,
  19. SKILL_TYPE,
  20. } from '../../enums/Enum'
  21. import {ComFindEnemy} from '../components/ComFindEnemy'
  22. import {Data} from '../../GameControl'
  23. import {ComAttackable} from '../components/ComAttackable'
  24. import {ComSkillAbel} from '../components/ComSkillAbel'
  25. import {SkillConfig} from '../../config/SkillConfig'
  26. import {cObject} from '../../collision/Object'
  27. import {ComMovable} from '../components/ComMovable'
  28. import {FrameAniConfig} from '../../config/FrameAniConfig'
  29. import {ComHasSkill} from '../components/ComHasSkill'
  30. const FILTER_SKILL = GenFilterKey([ComSkill, ComTransform, ComCocosNode])
  31. export class SysSkill extends ECSSystem {
  32. /** 连接 */
  33. public onAdd(world: FightWorld): void {}
  34. /** 断开连接 */
  35. public onRemove(world: FightWorld): void {}
  36. /** 添加实体 */
  37. public onEntityEnter(world: FightWorld, entity: number): void {}
  38. /** */
  39. public onEntityLeave(world: FightWorld, entity: number): void {}
  40. /** 更新 */
  41. public onUpdate(world: FightWorld, dt: number): void {
  42. let filterSkill = world.getFilter(FILTER_SKILL)
  43. //持续技能
  44. filterSkill.walk((entity: number) => {
  45. let comCocosNode = world.getComponent(entity, ComCocosNode)
  46. if (!comCocosNode.loaded) return
  47. let comSkill = world.getComponent(entity, ComSkill)
  48. let targetRole = world.getComponent(comSkill.role, ComRole)
  49. let comTransform = world.getComponent(entity, ComTransform)
  50. // 释放完的技能不再处理
  51. if (!comSkill.dirty) return
  52. let isOneRole = world.isOneRoleSkill(comSkill.skillCfg)
  53. //当技能是指向技能,目标死亡了,移除这个技能
  54. if (world.isDie(targetRole) && isOneRole) {
  55. world.removeSkillEntity(entity)
  56. return
  57. }
  58. comSkill.countDown -= dt
  59. if (isOneRole) {
  60. let targetComTransform = world.getComponent(comSkill.role, ComTransform)
  61. comTransform.x = targetComTransform.x + comSkill.skillCfg.offsetPos[1]
  62. comTransform.y =
  63. targetComTransform.y +
  64. targetComTransform.halfHeight * (comSkill.skillCfg.offsetPos[0] - 1) +
  65. comSkill.skillCfg.offsetPos[2]
  66. }
  67. let changeHpCb = entity => {
  68. let comHurtRole = world.getComponent(entity, ComRole)
  69. if (world.isDie(comHurtRole)) return
  70. let hpRateHurt = 0
  71. let isHurt = true
  72. //加BUFF
  73. let buffs = []
  74. for (let buffID of comSkill.skillCfg.buffs) {
  75. buffs.push(world.createBuff(buffID, comSkill.fightData))
  76. }
  77. if (comSkill.skillCfg.type != SKILL_TYPE.holo && buffs.length > 0) {
  78. for (let buff of buffs) {
  79. world.addBuff(entity, buff, comSkill.fightData)
  80. }
  81. }
  82. for (let i = 0; i < comSkill.skillCfg.effectType.length; i++) {
  83. let type = comSkill.skillCfg.effectType[i]
  84. if (type == SKILL_EFFECT_TYPE.rateHpHurt) {
  85. hpRateHurt = comSkill.skillCfg.effectParm[i][0]
  86. }
  87. }
  88. for (let i = 0; i < comHurtRole.buffs.length; i++) {
  89. for (let j = 0; j < comHurtRole.buffs[i].buffCfg.effectType.length; j++) {
  90. let type = comHurtRole.buffs[i].buffCfg.effectType[j]
  91. if (
  92. type == BUFF_EFFECT_TYPE.immune &&
  93. comHurtRole.buffs[i].buffCfg.effectParm[j].slice(0).includes(comSkill.skillCfg.ID)
  94. ) {
  95. if (comHurtRole.buffs[i].immuneTimes < comHurtRole.buffs[i].buffCfg.effectParm[j][0]) {
  96. comHurtRole.buffs[i].immuneTimes += 1
  97. } else {
  98. isHurt = false
  99. }
  100. }
  101. }
  102. }
  103. if (isHurt) {
  104. //百分比伤害加上固定伤害
  105. if (hpRateHurt > 0) {
  106. //受击特效统一处理,这里是0
  107. world.changeHpByHurt(entity, (comHurtRole.HP * hpRateHurt) / Data.game.rateNum, false, 0)
  108. }
  109. world.changeHpBySkill(comSkill, entity)
  110. }
  111. if (comSkill.skillCfg.hitID[HIT_ANI_TYPE.role]) {
  112. world.createAni(comSkill.skillCfg.hitID[HIT_ANI_TYPE.role], entity)
  113. }
  114. }
  115. if (comSkill.skillCfg.type == SKILL_TYPE.attackBack) {
  116. comSkill.cObject.containsBody.forEach((cbody, bodyEntity) => {
  117. let comBackRole = world.getComponent(bodyEntity, ComRole)
  118. if (world.isDie(comBackRole) || world.isEnter(bodyEntity)) return
  119. changeHpCb(bodyEntity)
  120. let comBackTransform = world.getComponent(bodyEntity, ComTransform)
  121. //免疫击退效果
  122. if (
  123. comBackRole.buffs.some(buff => {
  124. let buffCfg = buff.buffCfg
  125. return (
  126. buffCfg.buffType == BUFF_TYPE.negativeImmune &&
  127. buffCfg.effectParm[
  128. buffCfg.effectType.indexOf(BUFF_EFFECT_TYPE.immuneNegative)
  129. ]?.includes(NEGATIVE_TYPE.back)
  130. )
  131. })
  132. ) {
  133. return
  134. }
  135. let comBackFindEnemy = world.getComponent(bodyEntity, ComFindEnemy)
  136. let comBackAttackable = world.getComponent(bodyEntity, ComAttackable)
  137. let comBackSkillAbel = world.getComponent(bodyEntity, ComSkillAbel)
  138. let comBackCocosNode = world.getComponent(bodyEntity, ComCocosNode)
  139. let comBackHasSkill = world.getComponent(bodyEntity, ComHasSkill)
  140. // 修改X位置 --->修改成跟随技能一起移动 超过战场不动了
  141. if (
  142. (comTransform.x + comSkill.skillCfg.attackRangeX / 2 >= Data.game.fightSizeMaxX &&
  143. comBackRole.group != Data.game.gFriend) ||
  144. (comTransform.x - comSkill.skillCfg.attackRangeX / 2 <= Data.game.fightSizeMinX &&
  145. comBackRole.group == Data.game.gFriend)
  146. ) {
  147. return
  148. }
  149. comBackTransform.x =
  150. comTransform.x +
  151. ((comBackRole.group == Data.game.gFriend ? -1 : 1) * comSkill.skillCfg.attackRangeX) / 2
  152. let spineComTransform = world.getComponent(comBackRole.spineEntity, ComTransform)
  153. spineComTransform.x = comBackTransform.x
  154. // 此处必须让所有的cObject位置更新
  155. comBackCocosNode.node?.getComponents(cObject).forEach(cObject => {
  156. cObject.setPosition(cc.v3(comBackTransform.x, comTransform.y, 0))
  157. })
  158. // 移除自己的寻敌
  159. comBackFindEnemy.enemy = 0
  160. // 移除自己即将攻击 敌方即将被攻击
  161. let enemyComFindEnemy = world.getComponent(comBackFindEnemy.willAttackMelee, ComFindEnemy)
  162. if (enemyComFindEnemy) enemyComFindEnemy.willBeAttackMelee = 0
  163. comBackFindEnemy.willAttackMelee = 0
  164. // 移除自己被即将攻击 敌方即将攻击
  165. enemyComFindEnemy = world.getComponent(comBackFindEnemy.willBeAttackMelee, ComFindEnemy)
  166. if (enemyComFindEnemy) enemyComFindEnemy.willAttackMelee = 0
  167. comBackFindEnemy.willBeAttackMelee = 0
  168. //移除自己的攻击
  169. comBackAttackable.curAttack = 0
  170. //移除近战包围圈
  171. comBackAttackable.beAttacks.forEach(entity => {
  172. let beAttackComAttackable = world.getComponent(entity, ComAttackable)
  173. if (beAttackComAttackable) beAttackComAttackable.curAttack = 0
  174. })
  175. //移除顶盾技能
  176. comBackSkillAbel.isInShield = false
  177. let findIndex = comBackRole.buffs.findIndex(
  178. value => value.buffCfg.buffType == BUFF_TYPE.shieldReduceHurt,
  179. )
  180. if (findIndex != -1) {
  181. //将顶盾的buff去掉
  182. comBackRole.buffs.splice(findIndex, 1)
  183. //将顶盾的罩子,友军免疫远程攻击buff去掉
  184. world.removeNodeEntity(comBackSkillAbel.ani)
  185. let skillIndex = comBackRole.skills.findIndex(v => v.type == SKILL_TYPE.holo)
  186. if (skillIndex >= 0) {
  187. let allEntity = Array.from(comBackHasSkill.skillCObjects[skillIndex].containsBody.keys())
  188. allEntity = allEntity.filter(entityTmp => !world.isDie(entityTmp))
  189. allEntity.forEach(v => {
  190. let tmpComRole = world.getComponent(v, ComRole)
  191. let findIndex = tmpComRole.buffs.findIndex(
  192. value => value.buffCfg.buffType == BUFF_TYPE.rangedImmune,
  193. )
  194. if (findIndex != -1) {
  195. console.warn('去掉免疫buff')
  196. tmpComRole.buffs.splice(findIndex, 1)
  197. }
  198. })
  199. }
  200. }
  201. //将技能弹射子弹去除
  202. if (comBackSkillAbel.bullets) {
  203. comBackSkillAbel.bullets.forEach(v => {
  204. world.removeBulletEntity(v)
  205. })
  206. comBackSkillAbel.bullets.length = 0
  207. }
  208. //打断技能
  209. comBackSkillAbel.skillConfig = null
  210. comBackSkillAbel.roles.length = 0
  211. comBackSkillAbel.dirty = false
  212. })
  213. } else if (!comSkill.hurtFrameCompleted && comSkill.countDown <= comSkill.skillCfg.hurtFrame) {
  214. comSkill.hurtFrameCompleted = true
  215. if (isOneRole) {
  216. changeHpCb(comSkill.role)
  217. } else {
  218. let allEntity = Array.from(comSkill.cObject.containsBody.keys())
  219. allEntity = allEntity.filter(entityTmp => !world.isDie(entityTmp))
  220. for (let i = 0; i < Math.min(allEntity.length, comSkill.skillCfg.maxRole); i++) {
  221. changeHpCb(allEntity[i])
  222. }
  223. }
  224. }
  225. // 时间到的技能移除
  226. if (comSkill.countDown <= 0) {
  227. comSkill.dirty = false
  228. world.removeSkillEntity(entity)
  229. return
  230. }
  231. //绘制范围
  232. world.drawDebug(entity, comSkill.cObject)
  233. return false
  234. })
  235. }
  236. }