/** @format */ import {ComRole} from '../components/ComRole' import {ECSSystem} from '../lib/ECSSystem' import {GenFilterKey} from '../lib/ECSComponent' import {FightWorld} from '../worlds/FightWorld' import {ComCocosNode} from '../components/ComCocosNode' import {ComSkillAbel} from '../components/ComSkillAbel' import {ComHasSkill} from '../components/ComHasSkill' import {ComFindEnemy} from '../components/ComFindEnemy' import {Data} from '../../GameControl' import {EventBuffChange} from '../core/NodeEvent' import {ComDizzy} from '../components/ComDizzy' import {BT} from '../../behaviorTree/BehaviorTree' import {ComDie} from '../components/ComDie' import {ComAttackable} from '../components/ComAttackable' import {Log} from '../../utils/LogUtils' import {ROLE_TYPE, SKILL_DIR_TYPE, SKILL_EFFECT_TYPE, SKILL_TYPE} from '../../enums/Enum' import {ComBehaviorTree} from '../components/ComBehaviorTree' import {ComTransform} from '../components/ComTransform' export class SysHasSkill extends ECSSystem { FILTER_HAS_SKILL = GenFilterKey([ComHasSkill, ComSkillAbel, ComCocosNode, ComRole, ComBehaviorTree], [ComDie]) /** 连接 */ public onAdd(world: FightWorld): void {} /** 断开连接 */ public onRemove(world: FightWorld): void {} /** 添加实体 */ public onEntityEnter(world: FightWorld, entity: number): void {} /** */ public onEntityLeave(world: FightWorld, entity: number): void {} /** 更新 */ public onUpdate(world: FightWorld, dt: number): void { let filter = world.getFilter(this.FILTER_HAS_SKILL) filter.walk((entity: number) => { let comRole = world.getComponent(entity, ComRole) let comHasSkill = world.getComponent(entity, ComHasSkill) let comSkillAbel = world.getComponent(entity, ComSkillAbel) let comDizzy = world.getComponent(entity, ComDizzy) let comTransform = world.getComponent(entity, ComTransform) //晕眩的时候不判断是否有技能 if (comDizzy && comDizzy.dirty) return // 先判断技能CD for (let i = 0; i < comRole.skillCountDowns.length; i++) { let skillCfg = comRole.skills[i] let skillCObject = comHasSkill.skillCObjects[i] //处理光环要处理是否是伤害光环和是否是自己 if (skillCfg.type == SKILL_TYPE.holo && skillCObject) { let canAddBuff = true let leftTime = 0 //绿巨人顶盾才能加光环 if (skillCfg.effectType.includes(SKILL_EFFECT_TYPE.shieldHolo) && !comSkillAbel.isInShield) { canAddBuff = false } if (comSkillAbel.isInShield) { leftTime = comSkillAbel.countDown } if (canAddBuff) { //绘制范围 world.drawDebug(entity, skillCObject) skillCObject.curInBody.forEach(inBody => { let inBodyComRole = world.getComponent(inBody, ComRole) if (!world.isDie(inBodyComRole)) { for (let buffID of skillCfg.buffs) { let index = inBodyComRole.buffs.findIndex(v => skillCfg.buffs.includes(v.buffCfg.ID), ) if ( index < 0 && inBodyComRole.roleCfg.type != ROLE_TYPE.totem && inBodyComRole.roleCfg.type != ROLE_TYPE.base ) { let buff = world.createBuff(buffID, comRole) if (leftTime > 0) { buff.countDown = leftTime } world.addBuff(inBody, buff, comRole) } } } }) } skillCObject.curOutBody.forEach(body => { let outBodyComRole = world.getComponent(body, ComRole) if (!world.isDie(outBodyComRole)) { for (let buffID of skillCfg.buffs) { let index = outBodyComRole.buffs.findIndex(v => v.buffCfg.ID == buffID) if (index >= 0) { let removeBuffs = outBodyComRole.buffs.splice(index, 1) world.removeBuffAttr(body, removeBuffs[0]) // world // .getComponent(body, ComCocosNode) // .events.push(new EventBuffChange(outBodyComRole.buffs, [], removeBuffs)) } } } }) continue } //处理非光环可以施放的技能 comRole.skillCountDowns[i] -= dt //先判断角色不是在放技能,技能CD好了,特定技能达成条件可以施放 if (comRole.skillCountDowns[i] <= 0 && !comSkillAbel.dirty) { if ( skillCfg.minRole <= 0 && skillCfg.type != SKILL_TYPE.createRole && skillCfg.type != SKILL_TYPE.transRole ) { Log.error('非召唤技能,变身技能配置错误,没有角色最小数量', JSON.stringify(skillCfg)) continue } if (skillCfg.dirType == SKILL_DIR_TYPE.baby && comRole.babys.length == 0) { //没有宝宝可以释放技能 continue } if (skillCfg.type == SKILL_TYPE.createRole) { if ( skillCfg.createMax > 0 && comRole.babys.filter( baby => world.getComponent(baby, ComRole)?.roleCfg.ID == skillCfg.createRole[0], ).length >= skillCfg.createMax ) { //宝宝达到召唤上限 将CD设为最大值,等有宝宝死亡,再重置CD comRole.skillCountDowns[i] = Infinity continue } //召唤一次后不能再召唤 if (skillCfg.createMax <= 0) { comRole.skillCountDowns[i] = Infinity } } skillCObject.containsBody.forEach((value, key) => { if (world.isDie(key) || world.isEnter(key)) { skillCObject.containsBody.delete(key) } }) if (skillCObject.containsBody.size >= skillCfg.minRole) { let containsArr = skillCObject.containsBody.keysArr() for (let i = containsArr.length - 1; i >= 0; i--) { let targetComRole = world.getComponent(containsArr[i], ComRole) if (world.isBase(targetComRole)) { containsArr.splice(i, 1) } } containsArr.outOrder() if (skillCfg.type == SKILL_TYPE.moveBack) { // 检测背刺的时候自己没有打人,没有将要打人,没有将要被打,没有被近战打, 敌人正在攻击 let comFindEnemy = world.getComponent(entity, ComFindEnemy) let comAttackable = world.getComponent(entity, ComAttackable) // 检测背刺的时候自己没有打人,没有将要打人,没有将要被打,没有被近战打 if ( comAttackable.curAttack || comFindEnemy.willAttackMelee || comFindEnemy.willBeAttackMelee || comAttackable.beAttacks.length > 0 ) { continue } //敌军:敌军不是正在攻击目标或者是有背刺技能的敌人不触发背刺,敌军死亡不触发背刺 for (let i = containsArr.length - 1; i >= 0; i--) { let targetComAttackable = world.getComponent(containsArr[i], ComAttackable) let targetComRole = world.getComponent(containsArr[i], ComRole) if ( targetComAttackable.beAttacks.length == 0 || targetComRole.skills.find(v => v.type == SKILL_TYPE.moveBack) ) { containsArr.splice(i, 1) } } } if (skillCfg.dirType == SKILL_DIR_TYPE.minHpRole) { containsArr.sort((a, b) => { let aComAttackable = world.getComponent(a, ComAttackable) let bComAttackable = world.getComponent(b, ComAttackable) if (aComAttackable.isMelee != bComAttackable.isMelee) { return Number(bComAttackable.isMelee) - Number(aComAttackable.isMelee) } else { let aComRole = world.getComponent(a, ComRole) let bComRole = world.getComponent(b, ComRole) return aComRole.nowHP / aComRole.HP - bComRole.nowHP / bComRole.HP } }) if (containsArr.length > 1) containsArr.length = 1 } else if ( skillCfg.dirType == SKILL_DIR_TYPE.selfRole || skillCfg.dirType == SKILL_DIR_TYPE.selfNormal ) { containsArr.length = 0 containsArr.push(entity) //顶盾不能在前往攻击点施放 if (skillCfg.type == SKILL_TYPE.shield) { let comFindEnemy = world.getComponent(entity, ComFindEnemy) if (comFindEnemy?.willAttackMelee) { containsArr.length = 0 } } } else if (skillCfg.dirType == SKILL_DIR_TYPE.maxDistance) { let selfPos = cc.v2(comTransform.x, comTransform.y) containsArr.sort((a, b) => { //按照距离排序 let aComTrans = world.getComponent(a, ComTransform) let bComTrans = world.getComponent(b, ComTransform) if (aComTrans && bComTrans) { let aPos = cc.v2(aComTrans.x, aComTrans.y) let bPos = cc.v2(bComTrans.x, bComTrans.y) return bPos.sub(selfPos).mag() - aPos.subtract(selfPos).mag() } else { return 0 } }) } // 没有施放目标,判断下一个技能 if (containsArr.length <= 0 && skillCfg.minRole > 0) continue comSkillAbel.skillConfig = skillCfg comSkillAbel.roles.length = 0 if ( skillCfg.dirType == SKILL_DIR_TYPE.normal || skillCfg.dirType == SKILL_DIR_TYPE.selfNormal || skillCfg.dirType == SKILL_DIR_TYPE.selfRole || skillCfg.dirType == SKILL_DIR_TYPE.anyRole || skillCfg.dirType == SKILL_DIR_TYPE.minHpRole || skillCfg.dirType == SKILL_DIR_TYPE.maxDistance ) { if (containsArr[0]) comSkillAbel.roles.push(containsArr[0]) } else if (skillCfg.dirType == SKILL_DIR_TYPE.baby) { comRole.babys.forEach(baby => comSkillAbel.roles.push(baby)) } break } } } return false }) } }