SysSkillAbel.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /** @format */
  2. import {ECSSystem} from '../lib/ECSSystem'
  3. import {GenFilterKey} from '../lib/ECSComponent'
  4. import {FightWorld} from '../worlds/FightWorld'
  5. import {ComSkillAbel} from '../components/ComSkillAbel'
  6. import {ComTransform} from '../components/ComTransform'
  7. import {ComRole} from '../components/ComRole'
  8. import {ComCocosNode} from '../components/ComCocosNode'
  9. import {Data} from '../../GameControl'
  10. import {ccUtils} from '../../utils/ccUtils'
  11. import {ComMovable} from '../components/ComMovable'
  12. import {ComAttackable} from '../components/ComAttackable'
  13. import {ComDie} from '../components/ComDie'
  14. import {
  15. BUFF_TYPE,
  16. BULLET_EFFECT_TYPE,
  17. BULLET_FLY_TYPE,
  18. BULLET_TYPE,
  19. ENTRY,
  20. FRAME_ANI_NAME,
  21. GAME_ROLE_TIP,
  22. HIT_ANI_TYPE,
  23. SKILL_DIR_TYPE,
  24. SKILL_EFFECT_TYPE,
  25. SKILL_TYPE,
  26. } from '../../enums/Enum'
  27. import {ComFindEnemy} from '../components/ComFindEnemy'
  28. import {ComDizzy} from '../components/ComDizzy'
  29. import {cObject} from '../../collision/Object'
  30. import {EventRoleTip} from '../core/NodeEvent'
  31. import {ComBehaviorTree} from '../components/ComBehaviorTree'
  32. import {RoleConfig} from '../../config/RoleConfig'
  33. import {BulletConfig} from '../../config/BulletConfig'
  34. import {ComBullet} from '../components/ComBullet'
  35. import {cCollider} from '../../collision/Collider'
  36. import {EntryObj} from '../core/GameInterface'
  37. const FILTER_SKILLABEL = GenFilterKey([ComSkillAbel, ComTransform, ComRole, ComCocosNode, ComBehaviorTree], [ComDie])
  38. export class SysSkillAbel extends ECSSystem {
  39. /** 连接 */
  40. public onAdd(world: FightWorld): void {}
  41. /** 断开连接 */
  42. public onRemove(world: FightWorld): void {}
  43. /** 添加实体 */
  44. public onEntityEnter(world: FightWorld, entity: number): void {}
  45. /** */
  46. public onEntityLeave(world: FightWorld, entity: number): void {}
  47. /** 更新 */
  48. public onUpdate(world: FightWorld, dt: number): void {
  49. let filter = world.getFilter(FILTER_SKILLABEL)
  50. filter.walk((entity: number) => {
  51. let comRole = world.getComponent(entity, ComRole)
  52. let comCocosNode = world.getComponent(entity, ComCocosNode)
  53. let comSkillAbel = world.getComponent(entity, ComSkillAbel)
  54. let comTransform = world.getComponent(entity, ComTransform)
  55. if (!comSkillAbel.dirty) return
  56. let curSkillIndex = comRole.skills.findIndex(value => value.ID == comSkillAbel.skillConfig.ID)
  57. let fightData
  58. if (curSkillIndex > comRole.roleCfg.skills.length - 1) {
  59. fightData = {
  60. buffs: [],
  61. entryMap: new Map<ENTRY, EntryObj>(),
  62. createRole: entity,
  63. ...comRole.equips[curSkillIndex - comRole.roleCfg.skills.length],
  64. }
  65. }
  66. let addBuff = () => {
  67. let buffs = []
  68. for (let buffID of comSkillAbel.skillConfig.buffs) {
  69. buffs.push(world.createBuff(buffID, comRole))
  70. }
  71. comSkillAbel.roles.forEach(skillEntity => {
  72. //除开光环以外的buff技能
  73. if (comSkillAbel.skillConfig.type != SKILL_TYPE.holo && buffs.length > 0) {
  74. for (let buff of buffs) {
  75. world.addBuff(skillEntity, buff, comRole)
  76. }
  77. }
  78. })
  79. }
  80. if (comSkillAbel.startDirty) {
  81. //顶盾技能在吟唱开始的时候加buff 其他除了光环技能在技能伤害帧加BUFF
  82. if (comSkillAbel.skillConfig.type == SKILL_TYPE.shield && !comSkillAbel.isInShield) {
  83. comSkillAbel.isInShield = true
  84. addBuff()
  85. //顶盾特效
  86. if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role]) {
  87. comSkillAbel.ani = world.createAni(comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role], entity)
  88. }
  89. }
  90. if (comSkillAbel.skillConfig.type == SKILL_TYPE.skillBullet) {
  91. let comTrans = world.getComponent(comSkillAbel.roles[0], ComTransform)
  92. if (comTrans) {
  93. comSkillAbel.skillBulletPos = cc.v2(comTrans.x, comTrans.y)
  94. //瞄准特效
  95. if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role]) {
  96. world.createAni(
  97. comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role],
  98. undefined,
  99. comSkillAbel.skillBulletPos,
  100. )
  101. }
  102. } else {
  103. //让技能可以重新被施放
  104. let curSkillIndex = comRole.skills.findIndex(value => value.ID == comSkillAbel.skillConfig.ID)
  105. if (curSkillIndex >= 0) {
  106. comRole.skillCountDowns[curSkillIndex] = comRole.castTime[curSkillIndex]
  107. }
  108. }
  109. }
  110. comSkillAbel.bullets = []
  111. comSkillAbel.skillBulletTime = this.getSkillBulletInverter(comSkillAbel)
  112. comSkillAbel.skillBulletNum = 0
  113. comSkillAbel.startDirty = false
  114. }
  115. //发射多枚技能子弹
  116. if (
  117. comSkillAbel.skillConfig.type == SKILL_TYPE.skillBullet ||
  118. comSkillAbel.skillConfig.type == SKILL_TYPE.ejectionSkillBullet
  119. ) {
  120. let skillBulletParams =
  121. comSkillAbel.skillConfig.effectParm[
  122. comSkillAbel.skillConfig.effectType.indexOf(SKILL_EFFECT_TYPE.skillBullet)
  123. ]
  124. let bulletCfg = BulletConfig[skillBulletParams[0]]
  125. let bulletNum = skillBulletParams[1]
  126. comSkillAbel.skillBulletTime -= dt
  127. if (comSkillAbel.skillBulletTime <= 0 && comSkillAbel.skillBulletNum < bulletNum) {
  128. comSkillAbel.skillBulletNum += 1
  129. if (bulletCfg.flyType == BULLET_FLY_TYPE.boomerang) {
  130. let durRange =
  131. bulletCfg.effectParm[bulletCfg.effectType.indexOf(BULLET_EFFECT_TYPE.boomerangRange)][0]
  132. comSkillAbel.skillBulletPos = cc.v2(
  133. comTransform.x + durRange * (comTransform.dir.x > 0 ? 1 : -1),
  134. comTransform.y + comTransform.halfHeight,
  135. )
  136. }
  137. //0是吟唱时间平均值
  138. comSkillAbel.skillBulletTime = this.getSkillBulletInverter(comSkillAbel)
  139. if (comSkillAbel.skillConfig.type == SKILL_TYPE.skillBullet) {
  140. let tmp = world.createRoleSkillBulletEntity(
  141. comSkillAbel.skillConfig,
  142. skillBulletParams[0],
  143. entity,
  144. BulletConfig[skillBulletParams[0]]?.type == BULLET_TYPE.normal ||
  145. BulletConfig[skillBulletParams[0]]?.isEjection
  146. ? comSkillAbel.roles[0]
  147. : 0,
  148. Boolean(skillBulletParams[3]),
  149. comSkillAbel.skillBulletPos,
  150. )
  151. if (tmp.length > 0) {
  152. if (bulletCfg.flyType == BULLET_FLY_TYPE.boomerang) comSkillAbel.bullets.push(tmp[0])
  153. let comBullet = world.getComponent(tmp[0], ComBullet)
  154. if (fightData && comBullet) comBullet.fightData = fightData
  155. }
  156. } else if (comSkillAbel.skillConfig.type == SKILL_TYPE.ejectionSkillBullet) {
  157. let tmp = world.createRoleSkillBulletEntity(
  158. comSkillAbel.skillConfig,
  159. skillBulletParams[0],
  160. entity,
  161. 0,
  162. false,
  163. cc.v2(
  164. Math.randomRangeFloat(
  165. comRole.group == Data.game.gFriend ? comTransform.x : Data.game.fightSizeMinX,
  166. comRole.group == Data.game.gFriend ? Data.game.fightSizeMaxX : comTransform.x,
  167. ),
  168. Math.randomRangeFloat(Data.game.fightSizeMinY, Data.game.fightSizeMaxY),
  169. ),
  170. )
  171. if (tmp.length > 0) {
  172. comSkillAbel.bullets.push(tmp[0])
  173. }
  174. }
  175. }
  176. }
  177. comSkillAbel.countDown -= dt
  178. if (comSkillAbel.countDown <= comSkillAbel.castSkillTime && comSkillAbel.skillDirty) {
  179. comSkillAbel.skillDirty = false
  180. if (CC_DEV) ccUtils.setLabel('', comCocosNode?.node, 'skill')
  181. let comAttackable = world.getComponent(entity, ComAttackable)
  182. let comFindEnemy = world.getComponent(entity, ComFindEnemy)
  183. if (comSkillAbel.skillConfig.type == SKILL_TYPE.moveBack) {
  184. if (!world.isDie(comSkillAbel.roles[0])) {
  185. let targetComTrans = world.getComponent(comSkillAbel.roles[0], ComTransform)
  186. let targetComMovable = world.getComponent(comSkillAbel.roles[0], ComMovable)
  187. let targetComAttackable = world.getComponent(comSkillAbel.roles[0], ComAttackable)
  188. let comEnemyFindEnemy = world.getComponent(comSkillAbel.roles[0], ComFindEnemy)
  189. if (
  190. comAttackable.curAttack ||
  191. comFindEnemy.willBeAttackMelee ||
  192. comFindEnemy.willAttackMelee ||
  193. comAttackable.beAttacks.length > 0 ||
  194. comEnemyFindEnemy.willAttackMelee ||
  195. comEnemyFindEnemy.willBeAttackMelee ||
  196. targetComAttackable.beAttacks.length == 0
  197. ) {
  198. return
  199. }
  200. let targetPos = world.moveToMeleeAttackPos(
  201. entity,
  202. comTransform,
  203. targetComTrans,
  204. targetComMovable,
  205. true,
  206. )
  207. comTransform.x = targetPos.x
  208. comTransform.y = targetPos.y
  209. let comSpineTransform = world.getComponent(comRole.spineEntity, ComTransform)
  210. if (comSpineTransform) {
  211. comSpineTransform.x = targetPos.x
  212. comSpineTransform.y = targetPos.y
  213. }
  214. world.changeMoveSpeed(entity, 0)
  215. // 此处必须让所有的cObject位置更新
  216. comCocosNode.node?.getComponents(cObject).forEach(cObject => {
  217. cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0))
  218. })
  219. comAttackable.curAttack = comSkillAbel.roles[0]
  220. //背刺比较特殊,这次要处理被攻击数组
  221. if (!targetComAttackable.beAttacks.includes(entity)) {
  222. targetComAttackable.beAttacks.push(entity)
  223. }
  224. //把刺客完成背刺后提升暴击率的技能CD改成0秒
  225. comRole.skills.forEach((skill, index) => {
  226. if (
  227. skill.effectType.includes(SKILL_EFFECT_TYPE.castBySkill) &&
  228. skill.effectParm[0][0] == comSkillAbel.skillConfig.ID
  229. ) {
  230. comRole.skillCountDowns[index] = 0
  231. }
  232. })
  233. }
  234. } else if (
  235. comSkillAbel.skillConfig.type == SKILL_TYPE.normal ||
  236. comSkillAbel.skillConfig.type == SKILL_TYPE.addHP ||
  237. comSkillAbel.skillConfig.type == SKILL_TYPE.addShieldHPByHP ||
  238. comSkillAbel.skillConfig.type == SKILL_TYPE.attackBack
  239. ) {
  240. let isSuccess = world.createSkillByFightData(
  241. fightData ? fightData : comRole,
  242. comSkillAbel.skillConfig,
  243. comSkillAbel.roles,
  244. )
  245. //让没放成功的技能可以再次施放
  246. if (!isSuccess) {
  247. if (curSkillIndex >= 0) {
  248. //让技能可以重新被施放
  249. comRole.skillCountDowns[curSkillIndex] = comRole.castTime[curSkillIndex]
  250. }
  251. } else {
  252. //地板受击
  253. if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.floor]) {
  254. world.createAni(comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.floor], comSkillAbel.roles[0])
  255. }
  256. //自杀
  257. if (comSkillAbel.skillConfig.effectType.includes(SKILL_EFFECT_TYPE.killSelf)) {
  258. comRole.nowHP = 0
  259. comRole.HPDirty = true
  260. }
  261. }
  262. } else if (comSkillAbel.skillConfig.type == SKILL_TYPE.createRole) {
  263. comSkillAbel.skillConfig.createRole.forEach((role, index) => {
  264. if (role < 10000) {
  265. role = role * 100 + (comRole.roleCfg.ID % 100)
  266. }
  267. let cfg = RoleConfig[role]
  268. if (!cfg && comRole.group == Data.game.gEnemy) {
  269. cfg = world.fightCore.getRoleCfgByCfgID(role)
  270. }
  271. let baby = world.createRoleEntity(cfg, comRole.group == Data.game.gEnemy)
  272. //图腾特效
  273. if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role])
  274. world.createAni(comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role], baby)
  275. comRole.babys.push(baby)
  276. let babyComRole = world.getComponent(baby, ComRole)
  277. babyComRole.parent = entity
  278. babyComRole.parentRoleID = comRole.roleCfg.ID
  279. let babyComTransform = world.getComponent(baby, ComTransform)
  280. let babySpComTransform = world.getComponent(babyComRole.spineEntity, ComTransform)
  281. let pos = comSkillAbel.skillConfig.createRolePos[index]
  282. babyComTransform.x = comTransform.x + (comRole.group == Data.game.gEnemy ? -pos[0] : pos[0])
  283. babyComTransform.y = comTransform.y + pos[1]
  284. babySpComTransform.x = babyComTransform.x
  285. babySpComTransform.y = babyComTransform.y
  286. //角色表创建的宝宝,继承父角色的属性,怪物表遗迹表等没有养成,直接用固定值
  287. if (RoleConfig[role]) {
  288. let parentCfg = comRole.roleCfg
  289. babyComRole.nowHP = parentCfg.HP * (babyComRole.roleCfg.HP / Data.game.rateNum)
  290. babyComRole.lastHP = parentCfg.HP * (babyComRole.roleCfg.HP / Data.game.rateNum)
  291. babyComRole.HP = parentCfg.HP * (babyComRole.roleCfg.HP / Data.game.rateNum)
  292. babyComRole.attack = parentCfg.attack * (babyComRole.roleCfg.attack / Data.game.rateNum)
  293. babyComRole.spellAttack =
  294. parentCfg.spellAttack * (babyComRole.roleCfg.spellAttack / Data.game.rateNum)
  295. babyComRole.realAttack =
  296. parentCfg.realAttack * (babyComRole.roleCfg.realAttack / Data.game.rateNum)
  297. babyComRole.defense = parentCfg.defense * (babyComRole.roleCfg.defense / Data.game.rateNum)
  298. babyComRole.spellDefense =
  299. parentCfg.spellDefense * (babyComRole.roleCfg.spellDefense / Data.game.rateNum)
  300. }
  301. if (comRole.entryMap.get(ENTRY.addBabyHP)?.num) {
  302. babyComRole.HP *= 1 + comRole.entryMap.get(ENTRY.addBabyHP).num / Data.game.rateNum
  303. babyComRole.nowHP = babyComRole.HP
  304. babyComRole.lastHP = babyComRole.HP
  305. }
  306. if (comRole.entryMap.get(ENTRY.addBabyAttack)?.num) {
  307. babyComRole.attack *= 1 + comRole.entryMap.get(ENTRY.addBabyAttack).num / Data.game.rateNum
  308. babyComRole.spellAttack *=
  309. 1 + comRole.entryMap.get(ENTRY.addBabyAttack).num / Data.game.rateNum
  310. }
  311. })
  312. } else if (comSkillAbel.skillConfig.type == SKILL_TYPE.transRole) {
  313. let transID = comSkillAbel.skillConfig.createRole[0]
  314. if (transID < 10000) {
  315. transID = comSkillAbel.skillConfig.createRole[0] * 100 + (comRole.roleCfg.ID % 100)
  316. }
  317. let transRole = world.createRoleEntity(transID, comRole.group == Data.game.gEnemy)
  318. let comTransRole = world.getComponent(transRole, ComRole)
  319. let comTransTransform = world.getComponent(transRole, ComTransform)
  320. let comTransCocosNode = world.getComponent(transRole, ComCocosNode)
  321. let comSpineTransTransform = world.getComponent(comTransRole.spineEntity, ComTransform)
  322. comTransRole.lastHP = (comRole.nowHP / comRole.HP) * comTransRole.roleCfg.HP
  323. comTransRole.nowHP = comTransRole.lastHP
  324. comTransTransform.x = comTransform.x
  325. comTransTransform.y = comTransform.y
  326. comTransTransform.dir.x = comTransform.dir.x
  327. comTransTransform.dir.y = comTransform.dir.y
  328. if (comSpineTransTransform) {
  329. comSpineTransTransform.x = comTransform.x
  330. comSpineTransTransform.y = comTransform.y
  331. comSpineTransTransform.dir.x = comTransform.dir.x
  332. comSpineTransTransform.dir.y = comTransform.dir.y
  333. }
  334. //继承词条
  335. comRole.entryMap.forEach((entry, key) => {
  336. comTransRole.entryMap.set(key, entry)
  337. })
  338. //继承buff
  339. comTransRole.buffs = [...comRole.buffs]
  340. comRole.nowHP = 0
  341. comRole.shieldHP = 0
  342. comRole.HPDirty = true
  343. comRole.transDirty = true
  344. comTransRole.transID = comRole.roleCfg.ID
  345. }
  346. //放技能加血
  347. if (comRole.entryMap.get(ENTRY.skillRestoreHP)?.num > 0) {
  348. let addHPNum = comRole.entryMap.get(ENTRY.skillRestoreHP).num
  349. world.addHP(addHPNum, entity)
  350. comRole.HPDirty = true
  351. }
  352. }
  353. if (comSkillAbel.countDown <= 0) {
  354. if (comSkillAbel.bullets) {
  355. comSkillAbel.bullets.forEach(v => {
  356. world.removeBulletEntity(v)
  357. })
  358. comSkillAbel.bullets.length = 0
  359. }
  360. comSkillAbel.isInShield = false
  361. comSkillAbel.skillConfig = null
  362. comSkillAbel.roles.length = 0
  363. comSkillAbel.dirty = false
  364. }
  365. return false
  366. })
  367. }
  368. getSkillBulletInverter(comSkillAbel: ComSkillAbel): number {
  369. let cfg =
  370. comSkillAbel.skillConfig.effectParm[
  371. comSkillAbel.skillConfig.effectType.indexOf(SKILL_EFFECT_TYPE.skillBullet)
  372. ]
  373. if (!cfg) return 0
  374. let time = cfg[2] ? cfg[2] : +(comSkillAbel.castSkillTime / cfg[1]).toFixed(1)
  375. return Math.min(time, comSkillAbel.countDown)
  376. }
  377. }