SysHasSkill.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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 {ComSkillAbel} from '../components/ComSkillAbel'
  8. import {ComHasSkill} from '../components/ComHasSkill'
  9. import {ComFindEnemy} from '../components/ComFindEnemy'
  10. import {Data} from '../../GameControl'
  11. import {EventBuffChange} from '../core/NodeEvent'
  12. import {ComDizzy} from '../components/ComDizzy'
  13. import {BT} from '../../behaviorTree/BehaviorTree'
  14. import {ComDie} from '../components/ComDie'
  15. import {ComAttackable} from '../components/ComAttackable'
  16. import {Log} from '../../utils/LogUtils'
  17. import {ROLE_TYPE, SKILL_DIR_TYPE, SKILL_EFFECT_TYPE, SKILL_TYPE} from '../../enums/Enum'
  18. import {ComBehaviorTree} from '../components/ComBehaviorTree'
  19. import {ComTransform} from '../components/ComTransform'
  20. export class SysHasSkill extends ECSSystem {
  21. FILTER_HAS_SKILL = GenFilterKey([ComHasSkill, ComSkillAbel, ComCocosNode, ComRole, ComBehaviorTree], [ComDie])
  22. /** 连接 */
  23. public onAdd(world: FightWorld): void {}
  24. /** 断开连接 */
  25. public onRemove(world: FightWorld): void {}
  26. /** 添加实体 */
  27. public onEntityEnter(world: FightWorld, entity: number): void {}
  28. /** */
  29. public onEntityLeave(world: FightWorld, entity: number): void {}
  30. /** 更新 */
  31. public onUpdate(world: FightWorld, dt: number): void {
  32. let filter = world.getFilter(this.FILTER_HAS_SKILL)
  33. filter.walk((entity: number) => {
  34. let comRole = world.getComponent(entity, ComRole)
  35. let comHasSkill = world.getComponent(entity, ComHasSkill)
  36. let comSkillAbel = world.getComponent(entity, ComSkillAbel)
  37. let comDizzy = world.getComponent(entity, ComDizzy)
  38. let comTransform = world.getComponent(entity, ComTransform)
  39. //晕眩的时候不判断是否有技能
  40. if (comDizzy && comDizzy.dirty) return
  41. // 先判断技能CD
  42. for (let i = 0; i < comRole.skillCountDowns.length; i++) {
  43. let skillCfg = comRole.skills[i]
  44. let skillCObject = comHasSkill.skillCObjects[i]
  45. //处理光环要处理是否是伤害光环和是否是自己
  46. if (skillCfg.type == SKILL_TYPE.holo && skillCObject) {
  47. let canAddBuff = true
  48. let leftTime = 0
  49. //绿巨人顶盾才能加光环
  50. if (skillCfg.effectType.includes(SKILL_EFFECT_TYPE.shieldHolo) && !comSkillAbel.isInShield) {
  51. canAddBuff = false
  52. }
  53. if (comSkillAbel.isInShield) {
  54. leftTime = comSkillAbel.countDown
  55. }
  56. if (canAddBuff) {
  57. //绘制范围
  58. world.drawDebug(entity, skillCObject)
  59. skillCObject.curInBody.forEach(inBody => {
  60. let inBodyComRole = world.getComponent(inBody, ComRole)
  61. if (!world.isDie(inBodyComRole)) {
  62. for (let buffID of skillCfg.buffs) {
  63. let index = inBodyComRole.buffs.findIndex(v =>
  64. skillCfg.buffs.includes(v.buffCfg.ID),
  65. )
  66. if (
  67. index < 0 &&
  68. inBodyComRole.roleCfg.type != ROLE_TYPE.totem &&
  69. inBodyComRole.roleCfg.type != ROLE_TYPE.base
  70. ) {
  71. let buff = world.createBuff(buffID, comRole)
  72. if (leftTime > 0) {
  73. buff.countDown = leftTime
  74. }
  75. world.addBuff(inBody, buff, comRole)
  76. }
  77. }
  78. }
  79. })
  80. }
  81. skillCObject.curOutBody.forEach(body => {
  82. let outBodyComRole = world.getComponent(body, ComRole)
  83. if (!world.isDie(outBodyComRole)) {
  84. for (let buffID of skillCfg.buffs) {
  85. let index = outBodyComRole.buffs.findIndex(v => v.buffCfg.ID == buffID)
  86. if (index >= 0) {
  87. let removeBuffs = outBodyComRole.buffs.splice(index, 1)
  88. world.removeBuffAttr(body, removeBuffs[0])
  89. // world
  90. // .getComponent(body, ComCocosNode)
  91. // .events.push(new EventBuffChange(outBodyComRole.buffs, [], removeBuffs))
  92. }
  93. }
  94. }
  95. })
  96. continue
  97. }
  98. //处理非光环可以施放的技能
  99. comRole.skillCountDowns[i] -= dt
  100. //先判断角色不是在放技能,技能CD好了,特定技能达成条件可以施放
  101. if (comRole.skillCountDowns[i] <= 0 && !comSkillAbel.dirty) {
  102. if (
  103. skillCfg.minRole <= 0 &&
  104. skillCfg.type != SKILL_TYPE.createRole &&
  105. skillCfg.type != SKILL_TYPE.transRole
  106. ) {
  107. Log.error('非召唤技能,变身技能配置错误,没有角色最小数量', JSON.stringify(skillCfg))
  108. continue
  109. }
  110. if (skillCfg.dirType == SKILL_DIR_TYPE.baby && comRole.babys.length == 0) {
  111. //没有宝宝可以释放技能
  112. continue
  113. }
  114. if (skillCfg.type == SKILL_TYPE.createRole) {
  115. if (
  116. skillCfg.createMax > 0 &&
  117. comRole.babys.filter(
  118. baby => world.getComponent(baby, ComRole)?.roleCfg.ID == skillCfg.createRole[0],
  119. ).length >= skillCfg.createMax
  120. ) {
  121. //宝宝达到召唤上限 将CD设为最大值,等有宝宝死亡,再重置CD
  122. comRole.skillCountDowns[i] = Infinity
  123. continue
  124. }
  125. //召唤一次后不能再召唤
  126. if (skillCfg.createMax <= 0) {
  127. comRole.skillCountDowns[i] = Infinity
  128. }
  129. }
  130. skillCObject.containsBody.forEach((value, key) => {
  131. if (world.isDie(key) || world.isEnter(key)) {
  132. skillCObject.containsBody.delete(key)
  133. }
  134. })
  135. if (skillCObject.containsBody.size >= skillCfg.minRole) {
  136. let containsArr = skillCObject.containsBody.keysArr()
  137. for (let i = containsArr.length - 1; i >= 0; i--) {
  138. let targetComRole = world.getComponent(containsArr[i], ComRole)
  139. if (world.isBase(targetComRole)) {
  140. containsArr.splice(i, 1)
  141. }
  142. }
  143. containsArr.outOrder()
  144. if (skillCfg.type == SKILL_TYPE.moveBack) {
  145. // 检测背刺的时候自己没有打人,没有将要打人,没有将要被打,没有被近战打, 敌人正在攻击
  146. let comFindEnemy = world.getComponent(entity, ComFindEnemy)
  147. let comAttackable = world.getComponent(entity, ComAttackable)
  148. // 检测背刺的时候自己没有打人,没有将要打人,没有将要被打,没有被近战打
  149. if (
  150. comAttackable.curAttack ||
  151. comFindEnemy.willAttackMelee ||
  152. comFindEnemy.willBeAttackMelee ||
  153. comAttackable.beAttacks.length > 0
  154. ) {
  155. continue
  156. }
  157. //敌军:敌军不是正在攻击目标或者是有背刺技能的敌人不触发背刺,敌军死亡不触发背刺
  158. for (let i = containsArr.length - 1; i >= 0; i--) {
  159. let targetComAttackable = world.getComponent(containsArr[i], ComAttackable)
  160. let targetComRole = world.getComponent(containsArr[i], ComRole)
  161. if (
  162. targetComAttackable.beAttacks.length == 0 ||
  163. targetComRole.skills.find(v => v.type == SKILL_TYPE.moveBack)
  164. ) {
  165. containsArr.splice(i, 1)
  166. }
  167. }
  168. }
  169. if (skillCfg.dirType == SKILL_DIR_TYPE.minHpRole) {
  170. containsArr.sort((a, b) => {
  171. let aComAttackable = world.getComponent(a, ComAttackable)
  172. let bComAttackable = world.getComponent(b, ComAttackable)
  173. if (aComAttackable.isMelee != bComAttackable.isMelee) {
  174. return Number(bComAttackable.isMelee) - Number(aComAttackable.isMelee)
  175. } else {
  176. let aComRole = world.getComponent(a, ComRole)
  177. let bComRole = world.getComponent(b, ComRole)
  178. return aComRole.nowHP / aComRole.HP - bComRole.nowHP / bComRole.HP
  179. }
  180. })
  181. if (containsArr.length > 1) containsArr.length = 1
  182. } else if (
  183. skillCfg.dirType == SKILL_DIR_TYPE.selfRole ||
  184. skillCfg.dirType == SKILL_DIR_TYPE.selfNormal
  185. ) {
  186. containsArr.length = 0
  187. containsArr.push(entity)
  188. //顶盾不能在前往攻击点施放
  189. if (skillCfg.type == SKILL_TYPE.shield) {
  190. let comFindEnemy = world.getComponent(entity, ComFindEnemy)
  191. if (comFindEnemy?.willAttackMelee) {
  192. containsArr.length = 0
  193. }
  194. }
  195. } else if (skillCfg.dirType == SKILL_DIR_TYPE.maxDistance) {
  196. let selfPos = cc.v2(comTransform.x, comTransform.y)
  197. containsArr.sort((a, b) => {
  198. //按照距离排序
  199. let aComTrans = world.getComponent(a, ComTransform)
  200. let bComTrans = world.getComponent(b, ComTransform)
  201. if (aComTrans && bComTrans) {
  202. let aPos = cc.v2(aComTrans.x, aComTrans.y)
  203. let bPos = cc.v2(bComTrans.x, bComTrans.y)
  204. return bPos.sub(selfPos).mag() - aPos.subtract(selfPos).mag()
  205. } else {
  206. return 0
  207. }
  208. })
  209. }
  210. // 没有施放目标,判断下一个技能
  211. if (containsArr.length <= 0 && skillCfg.minRole > 0) continue
  212. comSkillAbel.skillConfig = skillCfg
  213. comSkillAbel.roles.length = 0
  214. if (
  215. skillCfg.dirType == SKILL_DIR_TYPE.normal ||
  216. skillCfg.dirType == SKILL_DIR_TYPE.selfNormal ||
  217. skillCfg.dirType == SKILL_DIR_TYPE.selfRole ||
  218. skillCfg.dirType == SKILL_DIR_TYPE.anyRole ||
  219. skillCfg.dirType == SKILL_DIR_TYPE.minHpRole ||
  220. skillCfg.dirType == SKILL_DIR_TYPE.maxDistance
  221. ) {
  222. if (containsArr[0]) comSkillAbel.roles.push(containsArr[0])
  223. } else if (skillCfg.dirType == SKILL_DIR_TYPE.baby) {
  224. comRole.babys.forEach(baby => comSkillAbel.roles.push(baby))
  225. }
  226. break
  227. }
  228. }
  229. }
  230. return false
  231. })
  232. }
  233. }