/** @format */ import {ECSSystem} from '../lib/ECSSystem' import {GenFilterKey} from '../lib/ECSComponent' import {FightWorld} from '../worlds/FightWorld' import {ComSkillAbel} from '../components/ComSkillAbel' import {ComTransform} from '../components/ComTransform' import {ComRole} from '../components/ComRole' import {ComCocosNode} from '../components/ComCocosNode' import {Data} from '../../GameControl' import {ccUtils} from '../../utils/ccUtils' import {ComMovable} from '../components/ComMovable' import {ComAttackable} from '../components/ComAttackable' import {ComDie} from '../components/ComDie' import { BUFF_TYPE, BULLET_EFFECT_TYPE, BULLET_FLY_TYPE, BULLET_TYPE, ENTRY, FRAME_ANI_NAME, GAME_ROLE_TIP, HIT_ANI_TYPE, SKILL_DIR_TYPE, SKILL_EFFECT_TYPE, SKILL_TYPE, } from '../../enums/Enum' import {ComFindEnemy} from '../components/ComFindEnemy' import {ComDizzy} from '../components/ComDizzy' import {cObject} from '../../collision/Object' import {EventRoleTip} from '../core/NodeEvent' import {ComBehaviorTree} from '../components/ComBehaviorTree' import {RoleConfig} from '../../config/RoleConfig' import {BulletConfig} from '../../config/BulletConfig' import {ComBullet} from '../components/ComBullet' import {cCollider} from '../../collision/Collider' import {EntryObj} from '../core/GameInterface' const FILTER_SKILLABEL = GenFilterKey([ComSkillAbel, ComTransform, ComRole, ComCocosNode, ComBehaviorTree], [ComDie]) export class SysSkillAbel extends ECSSystem { /** 连接 */ 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(FILTER_SKILLABEL) filter.walk((entity: number) => { let comRole = world.getComponent(entity, ComRole) let comCocosNode = world.getComponent(entity, ComCocosNode) let comSkillAbel = world.getComponent(entity, ComSkillAbel) let comTransform = world.getComponent(entity, ComTransform) if (!comSkillAbel.dirty) return let curSkillIndex = comRole.skills.findIndex(value => value.ID == comSkillAbel.skillConfig.ID) let fightData if (curSkillIndex > comRole.roleCfg.skills.length - 1) { fightData = { buffs: [], entryMap: new Map(), ...comRole.equips[curSkillIndex - comRole.roleCfg.skills.length], } } let addBuff = () => { let buffs = [] for (let buffID of comSkillAbel.skillConfig.buffs) { buffs.push(world.createBuff(buffID, comRole)) } comSkillAbel.roles.forEach(skillEntity => { //除开光环以外的buff技能 if (comSkillAbel.skillConfig.type != SKILL_TYPE.holo && buffs.length > 0) { for (let buff of buffs) { world.addBuff(skillEntity, buff, comRole) } } }) } if (comSkillAbel.startDirty) { //顶盾技能在吟唱开始的时候加buff 其他除了光环技能在技能伤害帧加BUFF if (comSkillAbel.skillConfig.type == SKILL_TYPE.shield && !comSkillAbel.isInShield) { comSkillAbel.isInShield = true addBuff() //顶盾特效 if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role]) { comSkillAbel.ani = world.createAni(comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role], entity) } } if (comSkillAbel.skillConfig.type == SKILL_TYPE.skillBullet) { let comTrans = world.getComponent(comSkillAbel.roles[0], ComTransform) if (comTrans) { comSkillAbel.skillBulletPos = cc.v2(comTrans.x, comTrans.y) //瞄准特效 if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role]) { world.createAni( comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role], undefined, comSkillAbel.skillBulletPos, ) } } else { //让技能可以重新被施放 let curSkillIndex = comRole.skills.findIndex(value => value.ID == comSkillAbel.skillConfig.ID) if (curSkillIndex >= 0) { comRole.skillCountDowns[curSkillIndex] = comRole.castTime[curSkillIndex] } } } comSkillAbel.bullets = [] comSkillAbel.skillBulletTime = this.getSkillBulletInverter(comSkillAbel) comSkillAbel.skillBulletNum = 0 comSkillAbel.startDirty = false } //发射多枚技能子弹 if ( comSkillAbel.skillConfig.type == SKILL_TYPE.skillBullet || comSkillAbel.skillConfig.type == SKILL_TYPE.ejectionSkillBullet ) { let skillBulletParams = comSkillAbel.skillConfig.effectParm[ comSkillAbel.skillConfig.effectType.indexOf(SKILL_EFFECT_TYPE.skillBullet) ] let bulletCfg = BulletConfig[skillBulletParams[0]] let bulletNum = skillBulletParams[1] comSkillAbel.skillBulletTime -= dt if (comSkillAbel.skillBulletTime <= 0 && comSkillAbel.skillBulletNum < bulletNum) { comSkillAbel.skillBulletNum += 1 if (bulletCfg.flyType == BULLET_FLY_TYPE.boomerang) { let durRange = bulletCfg.effectParm[bulletCfg.effectType.indexOf(BULLET_EFFECT_TYPE.boomerangRange)][0] comSkillAbel.skillBulletPos = cc.v2( comTransform.x + durRange * (comTransform.dir.x > 0 ? 1 : -1), comTransform.y + comTransform.halfHeight, ) } //0是吟唱时间平均值 comSkillAbel.skillBulletTime = this.getSkillBulletInverter(comSkillAbel) if (comSkillAbel.skillConfig.type == SKILL_TYPE.skillBullet) { let tmp = world.createRoleSkillBulletEntity( comSkillAbel.skillConfig, skillBulletParams[0], entity, BulletConfig[skillBulletParams[0]]?.type == BULLET_TYPE.normal || BulletConfig[skillBulletParams[0]]?.isEjection ? comSkillAbel.roles[0] : 0, Boolean(skillBulletParams[3]), comSkillAbel.skillBulletPos, ) if (tmp.length > 0) { if (bulletCfg.flyType == BULLET_FLY_TYPE.boomerang) comSkillAbel.bullets.push(tmp[0]) let comBullet = world.getComponent(tmp[0], ComBullet) if (fightData && comBullet) comBullet.fightData = fightData } } else if (comSkillAbel.skillConfig.type == SKILL_TYPE.ejectionSkillBullet) { let tmp = world.createRoleSkillBulletEntity( comSkillAbel.skillConfig, skillBulletParams[0], entity, 0, false, cc.v2( Math.randomRangeFloat( comRole.group == Data.game.gFriend ? comTransform.x : Data.game.fightSizeMinX, comRole.group == Data.game.gFriend ? Data.game.fightSizeMaxX : comTransform.x, ), Math.randomRangeFloat(Data.game.fightSizeMinY, Data.game.fightSizeMaxY), ), ) if (tmp.length > 0) { comSkillAbel.bullets.push(tmp[0]) } } } } comSkillAbel.countDown -= dt if (comSkillAbel.countDown <= comSkillAbel.castSkillTime && comSkillAbel.skillDirty) { comSkillAbel.skillDirty = false if (CC_DEV) ccUtils.setLabel('', comCocosNode?.node, 'skill') let comAttackable = world.getComponent(entity, ComAttackable) let comFindEnemy = world.getComponent(entity, ComFindEnemy) if (comSkillAbel.skillConfig.type == SKILL_TYPE.moveBack) { if (!world.isDie(comSkillAbel.roles[0])) { let targetComTrans = world.getComponent(comSkillAbel.roles[0], ComTransform) let targetComMovable = world.getComponent(comSkillAbel.roles[0], ComMovable) let targetComAttackable = world.getComponent(comSkillAbel.roles[0], ComAttackable) let comEnemyFindEnemy = world.getComponent(comSkillAbel.roles[0], ComFindEnemy) if ( comAttackable.curAttack || comFindEnemy.willBeAttackMelee || comFindEnemy.willAttackMelee || comAttackable.beAttacks.length > 0 || comEnemyFindEnemy.willAttackMelee || comEnemyFindEnemy.willBeAttackMelee || targetComAttackable.beAttacks.length == 0 ) { return } let targetPos = world.moveToMeleeAttackPos( entity, comTransform, targetComTrans, targetComMovable, true, ) comTransform.x = targetPos.x comTransform.y = targetPos.y let comSpineTransform = world.getComponent(comRole.spineEntity, ComTransform) if (comSpineTransform) { comSpineTransform.x = targetPos.x comSpineTransform.y = targetPos.y } world.changeMoveSpeed(entity, 0) // 此处必须让所有的cObject位置更新 comCocosNode.node?.getComponents(cObject).forEach(cObject => { cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0)) }) comAttackable.curAttack = comSkillAbel.roles[0] //背刺比较特殊,这次要处理被攻击数组 if (!targetComAttackable.beAttacks.includes(entity)) { targetComAttackable.beAttacks.push(entity) } //把刺客完成背刺后提升暴击率的技能CD改成0秒 comRole.skills.forEach((skill, index) => { if ( skill.effectType.includes(SKILL_EFFECT_TYPE.castBySkill) && skill.effectParm[0][0] == comSkillAbel.skillConfig.ID ) { comRole.skillCountDowns[index] = 0 } }) } } else if ( comSkillAbel.skillConfig.type == SKILL_TYPE.normal || comSkillAbel.skillConfig.type == SKILL_TYPE.addHP || comSkillAbel.skillConfig.type == SKILL_TYPE.addShieldHPByHP || comSkillAbel.skillConfig.type == SKILL_TYPE.attackBack ) { let isSuccess = world.createSkillByFightData( fightData ? fightData : comRole, comSkillAbel.skillConfig, comSkillAbel.roles, ) //让没放成功的技能可以再次施放 if (!isSuccess) { if (curSkillIndex >= 0) { //让技能可以重新被施放 comRole.skillCountDowns[curSkillIndex] = comRole.castTime[curSkillIndex] } } else { //地板受击 if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.floor]) { world.createAni(comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.floor], comSkillAbel.roles[0]) } //自杀 if (comSkillAbel.skillConfig.effectType.includes(SKILL_EFFECT_TYPE.killSelf)) { comRole.nowHP = 0 comRole.HPDirty = true } } } else if (comSkillAbel.skillConfig.type == SKILL_TYPE.createRole) { comSkillAbel.skillConfig.createRole.forEach((role, index) => { if (role < 10000) { role = role * 100 + (comRole.roleCfg.ID % 100) } let cfg = RoleConfig[role] if (!cfg && comRole.group == Data.game.gEnemy) { cfg = world.fightCore.getRoleCfgByCfgID(role) } let baby = world.createRoleEntity(cfg, comRole.group == Data.game.gEnemy) //图腾特效 if (comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role]) world.createAni(comSkillAbel.skillConfig.hitID[HIT_ANI_TYPE.role], baby) comRole.babys.push(baby) let babyComRole = world.getComponent(baby, ComRole) babyComRole.parent = entity babyComRole.parentRoleID = comRole.roleCfg.ID let babyComTransform = world.getComponent(baby, ComTransform) let babySpComTransform = world.getComponent(babyComRole.spineEntity, ComTransform) let pos = comSkillAbel.skillConfig.createRolePos[index] babyComTransform.x = comTransform.x + (comRole.group == Data.game.gEnemy ? -pos[0] : pos[0]) babyComTransform.y = comTransform.y + pos[1] babySpComTransform.x = babyComTransform.x babySpComTransform.y = babyComTransform.y //角色表创建的宝宝,继承父角色的属性,怪物表遗迹表等没有养成,直接用固定值 if (RoleConfig[role]) { let parentCfg = comRole.roleCfg babyComRole.nowHP = parentCfg.HP * (babyComRole.roleCfg.HP / Data.game.rateNum) babyComRole.lastHP = parentCfg.HP * (babyComRole.roleCfg.HP / Data.game.rateNum) babyComRole.HP = parentCfg.HP * (babyComRole.roleCfg.HP / Data.game.rateNum) babyComRole.attack = parentCfg.attack * (babyComRole.roleCfg.attack / Data.game.rateNum) babyComRole.spellAttack = parentCfg.spellAttack * (babyComRole.roleCfg.spellAttack / Data.game.rateNum) babyComRole.realAttack = parentCfg.realAttack * (babyComRole.roleCfg.realAttack / Data.game.rateNum) babyComRole.defense = parentCfg.defense * (babyComRole.roleCfg.defense / Data.game.rateNum) babyComRole.spellDefense = parentCfg.spellDefense * (babyComRole.roleCfg.spellDefense / Data.game.rateNum) } if (comRole.entryMap.get(ENTRY.addBabyHP)?.num) { babyComRole.HP *= 1 + comRole.entryMap.get(ENTRY.addBabyHP).num / Data.game.rateNum babyComRole.nowHP = babyComRole.HP babyComRole.lastHP = babyComRole.HP } if (comRole.entryMap.get(ENTRY.addBabyAttack)?.num) { babyComRole.attack *= 1 + comRole.entryMap.get(ENTRY.addBabyAttack).num / Data.game.rateNum babyComRole.spellAttack *= 1 + comRole.entryMap.get(ENTRY.addBabyAttack).num / Data.game.rateNum } }) } else if (comSkillAbel.skillConfig.type == SKILL_TYPE.transRole) { let transID = comSkillAbel.skillConfig.createRole[0] if (transID < 10000) { transID = comSkillAbel.skillConfig.createRole[0] * 100 + (comRole.roleCfg.ID % 100) } let transRole = world.createRoleEntity(transID, comRole.group == Data.game.gEnemy) let comTransRole = world.getComponent(transRole, ComRole) let comTransTransform = world.getComponent(transRole, ComTransform) let comTransCocosNode = world.getComponent(transRole, ComCocosNode) let comSpineTransTransform = world.getComponent(comTransRole.spineEntity, ComTransform) comTransRole.lastHP = (comRole.nowHP / comRole.HP) * comTransRole.roleCfg.HP comTransRole.nowHP = comTransRole.lastHP comTransTransform.x = comTransform.x comTransTransform.y = comTransform.y comTransTransform.dir.x = comTransform.dir.x comTransTransform.dir.y = comTransform.dir.y if (comSpineTransTransform) { comSpineTransTransform.x = comTransform.x comSpineTransTransform.y = comTransform.y comSpineTransTransform.dir.x = comTransform.dir.x comSpineTransTransform.dir.y = comTransform.dir.y } //继承词条 comRole.entryMap.forEach((entry, key) => { comTransRole.entryMap.set(key, entry) }) //继承buff comTransRole.buffs = [...comRole.buffs] comRole.nowHP = 0 comRole.shieldHP = 0 comRole.HPDirty = true comRole.transDirty = true comTransRole.transID = comRole.roleCfg.ID } //放技能加血 if (comRole.entryMap.get(ENTRY.skillRestoreHP)?.num > 0) { let addHPNum = comRole.entryMap.get(ENTRY.skillRestoreHP).num world.addHP(addHPNum, entity) comRole.HPDirty = true } } if (comSkillAbel.countDown <= 0) { if (comSkillAbel.bullets) { comSkillAbel.bullets.forEach(v => { world.removeBulletEntity(v) }) comSkillAbel.bullets.length = 0 } comSkillAbel.isInShield = false comSkillAbel.skillConfig = null comSkillAbel.roles.length = 0 comSkillAbel.dirty = false } return false }) } getSkillBulletInverter(comSkillAbel: ComSkillAbel): number { let cfg = comSkillAbel.skillConfig.effectParm[ comSkillAbel.skillConfig.effectType.indexOf(SKILL_EFFECT_TYPE.skillBullet) ] if (!cfg) return 0 let time = cfg[2] ? cfg[2] : +(comSkillAbel.castSkillTime / cfg[1]).toFixed(1) return Math.min(time, comSkillAbel.countDown) } }