SysSkillAbel.ts 20 KB

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