Files
heros/assets/script/game/skills/SkillCom.ts
2025-06-25 17:00:43 +08:00

261 lines
9.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { _decorator,Collider2D ,Contact2DType,v3,IPhysics2DContact,Vec3, tween, math, RigidBody2D, Animation, sp, Tween} 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 { smc } from "../common/SingletonModuleComp";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { AType, EType, RType, SkillSet } from "../common/config/SkillSet";
import { BoxSet, FacSet } from "../common/config/BoxSet";
import { HeroFac, HeroSet } from "../common/config/heroSet";
import { HeroViewComp } from "../hero/HeroViewComp";
import { BezierMove } from "../BezierMove/BezierMove";
import { FightConComp } from "../map/FightConComp";
import { MonModelComp } from "../hero/MonModelComp";
import { FightSet } from "../common/config/Mission";
import { HeroModelComp } from "../hero/HeroModelComp";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('SkillCom')
@ecs.register('SkillCom')
export class SkillCom extends CCComp {
s_uuid:number = 0;
s_name:string = "";
hero:number = 0;
speed:number = 200;
scale:number = 1;
angle:number = 0;
atk_count:number = 0;
is_destroy:boolean = false;
enemys:any = [];
AType: number = 0; // 运动类型
startPos: Vec3 = v3(); // 起始位置
targetPos: Vec3 = v3(); // 目标位置
duration: number = 0; // 技能持续时间
prefabName: string = ""; // 预制体名称
animName: string = "";
group:number = 0; //阵营
fac:number=0; //阵营
caster:any=null;
distance_x:number=0;
distance_y:number=0;
ap:number=0;
FIGHTCON:FightConComp=null;
run_time:number=0;
hited_time:number=0;
hit_count:number=0;
spine:sp.Skeleton=null;
anim:Animation=null;
tweenInstance:Tween<any> = null;
t_end_x:number=0;
caster_crit:number=0;
caster_crit_d:number=0;
private moveDirection: Vec3 | null = null; // 添加一个属性来存储移动方向
protected onLoad(): void {
this.FIGHTCON=this.node.parent.getComponent(FightConComp)
}
start() {
this.node.setPosition(this.startPos.x,this.startPos.y,0)
if(this.node.getChildByName('anm')){
this.spine=this.node.getChildByName('anm').getComponent('sp.Skeleton') as sp.Skeleton;
}else{
this.anim=this.node.getComponent(Animation)
}
oops.message.on(GameEvent.MissionEnd, this.doDestroy, this);
this.node.active = true;
console.log("[SkillCom]:caster",this.caster)
let collider = this.getComponent(Collider2D);
if(collider) {
collider.group = this.group;
collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
}
// console.log(this.group +"技能 collider ",collider);
switch(SkillSet[this.s_uuid].AType){
case AType.parabolic:
this.node.angle +=10
let bm=this.node.getComponent(BezierMove)
// bm.speed=700
if(this.group==BoxSet.MONSTER) bm.controlPointSide=-1
bm.moveTo(this.targetPos)
break;
case AType.linear:
// this.distance_x=SkillSet[this.s_uuid].in*this.speed
// this.t_end_x =400
// if(this.group==BoxSet.MONSTER){
// this.t_end_x=-400
// this.node.scale=v3(this.node.scale.x*-1,1,1)
// }
// this.tweenInstance = tween(this.node).to(SkillSet[this.s_uuid].in, { position:v3(this.t_end_x,this.node.position.y,0)},{
// onComplete: (target?: object) => {
// // this.node.setPosition(tx,this.node.position.y-300,0)
// }
// }).start()
break;
case AType.fixedStart:
break;
case AType.fixedEnd:
this.node.setPosition(this.targetPos.x,this.targetPos.y,0)
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);
}
if(this.node.getChildByName('anm')){
if(this.node.getChildByName('anm').getComponent('sp.Skeleton')){
console.log("[SkillCom]:has spine",this.spine)
this.spine.setCompleteListener((trackEntry) => {
this.onAnimationFinished()
console.log("[SkillCom]:[track %s][animation %s] complete: %s", trackEntry.trackIndex);
});
}
}
break;
}
}
onAnimationFinished(){
if(SkillSet[this.s_uuid].EType==EType.timeEnd) return
this.is_destroy=true
}
//范围伤害
range_damage(){
this.hit_count++
let enemys=ecs.query(ecs.allOf(MonModelComp))
if(this.fac==FacSet.MON) enemys=ecs.query(ecs.allOf(HeroModelComp))
enemys.forEach(entity => {
let view=entity.get(HeroViewComp)
if(view){
let dis =Math.abs(this.node.position.x-view.node.position.x)
if(dis > SkillSet[this.s_uuid].with) return
view.do_atked(this.ap,this.caster_crit,this.caster_crit_d)
}
});
}
//单体伤害
single_damage(target:HeroViewComp,crit:number=0,crit_d:number=0){
this.hit_count++
console.log("[SkillCom]:onBeginContact hit_count:",this.hit_count,SkillSet[this.s_uuid].hit)
if(this.hit_count>=SkillSet[this.s_uuid].hit) this.is_destroy=true // 技能命中次数
if(target == null) return;
target.do_atked(this.ap,crit,crit_d)
if(SkillSet[this.s_uuid].debuff>0){
let debuff =this.get_debuff()
target.add_debuff(SkillSet[this.s_uuid].debuff,debuff.deV,debuff.deC)
}
}
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
// console.log(this.scale+"碰撞开始 ",seCol,oCol);
let target = oCol.getComponent(HeroViewComp)
if(oCol.group!=this.group){
if(target == null) return;
this.single_damage(target,this.caster_crit,this.caster_crit_d)
// this.ent.destroy()
}
}
get_debuff(){ //debuff 加成
let debuff = {deV:0,deC:0}
let buff=null
if(this.caster.is_master) buff = this.FIGHTCON.hero_buff
if(this.caster.is_friend) buff = this.FIGHTCON.friend_buff
if(this.caster.is_boss||this.caster.is_kalami) buff = this.FIGHTCON.enemy_buff
if(buff==null) return debuff
debuff.deV=buff.DEBUFF_VALUE
debuff.deC=buff.DEBUFF_COUNT
return debuff
}
private startLinearMove(dt: number) {
if (!this.speed || this.is_destroy) return;
// 使用角度方向移动
const newX = this.node.position.x + this.speed * dt;
const newY = this.node.position.y;
this.node.setPosition(newX, this.node.position.y, this.node.position.z);
// 检查是否超出边界
if (newX < -400 || newX > 400) {
this.is_destroy = true;
}
}
update(deltaTime: number) {
let config=SkillSet[this.s_uuid]
if(smc.mission.pause) {
if(this.spine) this.spine.paused=true
if(this.anim) this.anim.pause()
return;
}
if(this.anim) this.anim.resume()
if(this.spine) this.spine.paused=false
if (!this.node || !this.node.isValid) return;
if(config.EType==EType.timeEnd){
this.run_time+=deltaTime
if(this.run_time>config.in){
console.log("[SkillCom]: timeEnd destroy",this.s_uuid,this.run_time)
this.is_destroy=true
}
}
//范围伤害
this.hited_time+=deltaTime
if(this.hited_time>config.hited&&this.hit_count == 0&&(config.EType==EType.animationEnd||config.EType==EType.timeEnd)){
this.hited_time=0
this.range_damage()
}
//直线移动
if(this.AType == AType.linear) this.startLinearMove(deltaTime);
this.toDestroy();
}
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
}
to_console(value:any,value2:any=null,value3:any=null){
console.log("[SkillCom]:["+this.s_name+this.s_uuid+"]:",value,value2,value3)
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.is_destroy = false;
this.AType = 0;
this.speed = 0;
this.startPos.set();
this.targetPos.set();
this.moveDirection = null; // 重置移动方向
// 先移除所有碰撞回调
const collider = this.getComponent(Collider2D);
if (collider) {
collider.off(Contact2DType.BEGIN_CONTACT);
}
this.scheduleOnce(() => {
this.node.destroy();
}, 0);
}
}