import { _decorator, Animation, CCBoolean, Collider2D, Contact2DType, Tween, UITransform, v3, Vec3 } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { BezierMove } from "../BezierMove/BezierMove"; import { DTType, EType, SkillSet, SType } from "../common/config/SkillSet"; import { BoxSet, FacSet } from "../common/config/BoxSet"; import { HeroViewComp } from "../hero/HeroViewComp"; import { GameEvent } from "../common/config/GameEvent"; import { smc } from "../common/SingletonModuleComp"; import { Attrs } from "../common/config/HeroAttrs"; const { ccclass, property } = _decorator; /** 视图层对象 */ @ccclass('AtkConCom') @ecs.register('AtkCon', false) export class AtkConCom extends CCComp { @property public anmEnd: boolean = false; @property public cbox: boolean = false; // 核心标识和配置 s_uuid:number = 0; // 运行时状态(必须缓存的) is_destroy:boolean = false; startPos: Vec3 = v3(); // 起始位置 targetPos: Vec3 = v3(); // 目标位置 group:number = 0; //阵营 fac:number=0; //阵营 run_time:number = 0; // 战斗相关运行时数据 Attrs:any=null hit_count:number = 0; // 组件引用 anim:Animation=null; tweenInstance:Tween = null; private moveDirection: Vec3 | null = null; // 添加一个属性来存储移动方向 // 缓存的配置对象(避免重复查找) public Config: any = null; private isInitialized: boolean = false; private initializeConfig() { if (this.isInitialized) return; // 缓存技能配置,避免重复查找 this.Config = SkillSet[this.s_uuid]; if (!this.Config) { // console.error("[SkillCom] 技能配置不存在:", this.s_uuid); return; } this.isInitialized = true; // console.log("[SkillCom] 技能配置初始化完成:", this.s_uuid, this.Config.name); } start() { this.initializeConfig(); // var entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象 // this.on(ModuleEvent.Cmd, this.onHandler, this); this.anim=this.node.getComponent(Animation) this.on(GameEvent.MissionEnd, this.doDestroy, this); this.node.active = true; let collider = this.getComponent(Collider2D); if(collider) { collider.group = this.group; collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); } } do_anim(){ if(this.node.getComponent(Animation)){ let anim = this.node.getComponent(Animation); //console.log("[SkillCom]:has anim",anim) anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this); } } do_parabolic(){ let bm=this.node.getComponent(BezierMove) this.node.angle +=10 // bm.speed=700 if(this.group==BoxSet.MONSTER) {bm.controlPointSide=-1 } bm.rotationSmoothness=0.6 bm.moveTo(this.targetPos) } do_line(){ let bm=this.node.getComponent(BezierMove) let s_x=this.startPos.x let s_y=this.startPos.y let t_x=this.targetPos.x let t_y=this.targetPos.y // 设定目标x this.targetPos.x = 400; if(this.group == BoxSet.MONSTER) { bm.controlPointSide = -1; this.targetPos.x = -400; } // 计算斜率 const k = (t_y - s_y) / (t_x - s_x); // 按直线公式计算新的y this.targetPos.y = k * (this.targetPos.x - s_x) + s_y; bm.controlPointOffset=0 bm.rotationSmoothness=0.6 bm.moveTo(this.targetPos); } do_fixedEnd(){ this.node.setPosition(this.targetPos.x > 360?300:this.targetPos.x,this.node.position.y,0) this.do_anim() } do_fixedStart(){ this.node.setPosition(this.startPos.x > 360?300:this.startPos.x,this.node.position.y,0) this.do_anim() } onAnimationFinished(){ // console.log("[SkillCom]:onAnimationFinished",this.s_uuid) if (!this.Config) return; if(this.Config.EType==EType.timeEnd) return if(this.Config.SType!=SType.damage){ } this.is_destroy=true } onBeginContact (seCol: Collider2D, oCol: Collider2D) { // console.log(this.scale+"碰撞开始 ",seCol,oCol); if(seCol.node.position.x-oCol.node.position.x > 100 ) return let target = oCol.getComponent(HeroViewComp) if(oCol.group!=this.group){ if(target == null) return; if (!this.Config) return; // console.log("[SkillCom]:onBeginContact oCol||seCol",oCol.node.position,seCol.node.position) this.single_damage(target,this.Config.DTType==DTType.range?true:false) // this.ent.destroy() } } //单体伤害 single_damage(target:HeroViewComp,is_range:boolean=false){ // //console.log("[SkillCom]:onBeginContact hit_count:",this.hit_count,SkillSet[this.s_uuid].hit) // if(this.hit_count > 0&&!is_range) this.ap=this.ap*(50+this.puncture_damage)/100 // 穿刺后 伤害减半,过滤范围伤害 if(target == null) return; if (!this.Config) return; let damage=Math.floor(this.Attrs[Attrs.AP]*(SkillSet[this.s_uuid].ap/100)) if(this.hit_count > 0 &&!is_range ){ let Percentage=Math.pow((50+this.Attrs[Attrs.PUNCTURE_DMG])/100, this.hit_count) damage=damage*Percentage } target.do_atked(damage,this.Attrs,this.s_uuid) // ap 及暴击 属性已经在skill.ts 处理 // console.log("[SkillCom]:single_damage t:tp:rtp",this.node.position,this.targetPos,target.node.position) this.hit_count++ // console.log("[SkillCom]:碰撞次数:技能次数:穿刺次数",this.hit_count,this.Config.hit,this.puncture) if(this.hit_count>=(this.Config.hit+this.Attrs[Attrs.PUNCTURE])&&(this.Config.DTType!=DTType.range)&&(this.Config.EType!=EType.animationEnd)&&(this.Config.EType!=EType.timeEnd)) this.is_destroy=true // 技能命中次数 } update(deltaTime: number) { // 确保配置已初始化(处理 update 可能先于 start 执行的情况) if (!this.isInitialized) { this.initializeConfig(); if (!this.Config) return; } if(smc.mission.pause) { if(this.anim) this.anim.pause() return; } if(this.anim) this.anim.resume() if (!this.node || !this.node.isValid) return; if(this.Config.EType==EType.timeEnd){ this.run_time+=deltaTime if(this.run_time>this.Config.in){ // //console.log("[SkillCom]: timeEnd destroy",this.s_uuid,this.run_time) this.is_destroy=true } } this.toDestroy(); } public atk(args:any){ let dis=this.node.getComponent(UITransform).width/2 let targetsInRange: HeroViewComp[] = [] // 收集范围内所有敌方目标 ecs.query(ecs.allOf(HeroViewComp)).some(e => { const view = e.get(HeroViewComp); if(view.fac!=this.fac) { const distance = Math.abs(this.node.position.x - view.node.position.x); if(distance <= dis) { targetsInRange.push(view); } } }); // 根据配置的hit_num决定攻击模式 const hitNum = SkillSet[this.s_uuid].hit_num || 0; if(hitNum > 0) { // 限制目标数量:按距离排序,选择最近的N个目标 if(targetsInRange.length > 0) { // 按距离排序(从近到远) targetsInRange.sort((a, b) => { const distanceA = Math.abs(this.node.position.x - a.node.position.x); const distanceB = Math.abs(this.node.position.x - b.node.position.x); return distanceA - distanceB; }); // 限制目标数量 const maxTargets = Math.min(hitNum, targetsInRange.length); const selectedTargets = targetsInRange.slice(0, maxTargets); selectedTargets.forEach(target => { this.single_damage(target, false); }); } } else { // 范围伤害:对所有范围内目标造成伤害 if(targetsInRange.length > 0) { targetsInRange.forEach(target => { this.single_damage(target, false); }); } } } toDestroy() { if(this.is_destroy){ if (this.ent) { this.ent.destroy(); } else { // 如果ent不存在,直接销毁节点 if (this.node && this.node.isValid) { this.node.destroy(); } } } } doDestroy(){ // //console.log("[SkillCom]:doDestroy") this.is_destroy=true } reset() { this.node.destroy(); } }