Files
heros/assets/script/game/skills/SkillCom.ts
2025-06-24 21:08:46 +08:00

260 lines
10 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)
if(this.caster.fac==FacSet.HERO){
if(this.caster.is_master){
this.caster_crit = this.caster.crit+this.FIGHTCON.hero_buff.CRITICAL+this.FIGHTCON.hero_debuff.CRITICAL
this.caster_crit_d = this.caster.crit_d+this.FIGHTCON.hero_buff.CRITICAL_DMG
}else{
this.caster_crit = this.caster.crit+this.FIGHTCON.friend_buff.CRITICAL+this.FIGHTCON.hero_debuff.CRITICAL
this.caster_crit_d = this.caster.crit_d+this.FIGHTCON.friend_buff.CRITICAL_DMG
}
}else{
this.caster_crit = this.caster.crit+this.FIGHTCON.enemy_buff.CRITICAL+this.FIGHTCON.enemy_debuff.CRITICAL
this.caster_crit_d = this.caster.crit_d+this.FIGHTCON.enemy_buff.CRITICAL_DMG
}
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){
target.add_debuff(SkillSet[this.s_uuid].debuff,SkillSet[this.s_uuid].deV,SkillSet[this.s_uuid].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()
}
}
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);
}
}