Files
heros/assets/script/game/hero/SkillConComp.ts
walkpan a3e4e70d9d feat(hero): 初始化角色和怪物技能数据,修改技能数据引用
- 在Hero实体中初始化技能数组,添加技能UUID和冷却时间信息
- 在Monster实体中遍历怪物技能,准备技能相关数据
- 在HeroViewComp中新增skills属性以存储技能信息
- 在SkillEnt中修正技能属性赋值,使用深拷贝避免引用问题
- 删除SkillConComp中无用的空行,优化update方法代码格式
2025-10-17 22:29:10 +08:00

176 lines
6.1 KiB
TypeScript

import { _decorator, Component, Node, ProgressBar, v3, Vec3 } from 'cc';
import { HeroViewComp } from './HeroViewComp';
import { Attrs, DBuff, SkillSet, SType, TGroup, } from '../common/config/SkillSet';
import { ecs } from 'db://oops-framework/libs/ecs/ECS';
import { GameEvent } from '../common/config/GameEvent';
import { FacSet } from '../common/config/BoxSet';
import { smc } from '../common/SingletonModuleComp';
import { CCComp } from 'db://oops-framework/module/common/CCComp';
import { MonModelComp } from './MonModelComp';
import { HeroModelComp } from './HeroModelComp';
import { SkillEnt } from '../skill/SkillEnt';
const { ccclass, property } = _decorator;
@ccclass('SkillCon')
@ecs.register('SkillCon')
export class SkillConComp extends CCComp {
HeroView:any=null;
HeroEntity:any=null;
skill_cd=0
private _timers: { [key: string]: any } = {};
init(): void {
this.on(GameEvent.FightEnd, this.clear_timer, this);
}
onLoad(){
this.HeroView=this.node.getComponent(HeroViewComp)
// //console.log(this.HeroView.uid+"=>"+this.HeroView.hero_name+"=> SkillConComp onLoad")
}
start() {
// //console.log(this.HeroView.uuid+"=>"+this.HeroView.hero_name+"=> SkillConComp start")
this.HeroEntity=this.HeroView.ent
}
update(dt: number) {
if(!smc.mission.play||smc.mission.pause) return
if(!this.HeroView.isStun() && !this.HeroView.isFrost()) {
let skills=this.HeroView.skills
for(let i=0;i<skills.length;i++){
skills[i].cd += dt;
if(skills[i].cd > skills[i].cd_max&&this.HeroView.mp >= skills[i].cost){
if(SkillSet[skills[i].uuid].SType==SType.damage&&this.HeroView.is_atking){
this.castSkill(SkillSet[skills[i].uuid])
this.HeroView.skills[i].cd = 0
this.HeroView.mp -= skills[i].cost
}
}
}
}
}
/** 施放技能 */
castSkill(config: typeof SkillSet[keyof typeof SkillSet]) {
// //console.log(view.uuid+"=>"+view.hero_name+"施放技能:"+config.uuid);
let wfuny=this.check_wfuny()
let dmg=0
this.doSkill(config,wfuny,dmg);
}
private doSkill(config: typeof SkillSet[keyof typeof SkillSet],is_wfuny:boolean=false,dmg:number=0) {
// 添加节点有效性检查
if (!this.node || !this.node.isValid || !this.HeroView || !this.HeroView.node || !this.HeroView.node.isValid) {
return;
}
let targets:any=null
if(config.TGroup==TGroup.Self){
targets = [this.node.position]
}
if(config.TGroup==TGroup.Enemy){
targets = this.selectTargets(config.t_num)
}
this.HeroView.playSkillEffect(config.uuid)
const sEnt = ecs.getEntity<SkillEnt>(SkillEnt);
const timerId = setTimeout(() => {
// 再次检查节点有效性
if (!this.node || !this.node.isValid || !this.HeroView || !this.HeroView.node || !this.HeroView.node.isValid) {
return;
}
console.log("技能开始",sEnt)
sEnt.load(
this.node.position,
this.node.parent,
config.uuid,
targets,
this.HeroView,
dmg
);
}, 300);
if(is_wfuny){
this.scheduleOnce(()=>{
this.HeroView.ex_show("blue")
this.doSkill(config,false,dmg)
},0.1)
}
// 保存定时器ID
this._timers[`skill_${config.uuid}`] = timerId;
}
check_wfuny(){
let random = Math.random()*100
if(random < this.HeroView.Attrs[Attrs.WFUNY]){
return true
}
return false
}
check_target(){
if(this.HeroView.fac==FacSet.HERO){
return ecs.query(ecs.allOf(MonModelComp))
}else{
return ecs.query(ecs.allOf(HeroModelComp))
}
}
get_front(entities:any){
let keyPos = this.HeroView.fac==FacSet.HERO ?
Math.min(...entities.map(e => e.get(HeroViewComp).node.position.x)) :
Math.max(...entities.map(e => e.get(HeroViewComp).node.position.x));
let keyEntity = entities.find(e => e.get(HeroViewComp).node.position.x === keyPos);
return keyEntity.get(HeroViewComp).node.position;
}
/**
* 选择目标(整合版)
* @param t_num 目标数量,第一个是最近的前排,后续随机(可重复)
* @returns 目标坐标数组
*/
private selectTargets(t_num: number): Vec3[] {
const targets: Vec3[] = [];
const entities = this.check_target();
// 如果没有目标实体
if (entities.length === 0) {
const defaultPos = this.HeroView.fac === FacSet.HERO ? v3(400, 0, 0) : v3(-400, 0, 0);
// 返回t_num个相同的默认位置
for (let i = 0; i < t_num; i++) {
targets.push(defaultPos.clone());
}
return targets;
}
// 第一个目标:最前排(离施法者最近的)
const frontPos = this.get_front(entities);
targets.push(v3(frontPos.x, frontPos.y, 0));
// 后续目标:随机选择(可以重复)
for (let i = 1; i < t_num; i++) {
const randomEntity = entities[Math.floor(Math.random() * entities.length)];
const randomPos = randomEntity.get(HeroViewComp).node.position;
targets.push(v3(randomPos.x, randomPos.y, 0));
}
return targets;
}
public clear_timer() {
// console.log("[SkillConComp]:clear_timer",this.HeroView);
Object.values(this._timers).forEach(clearTimeout);
}
reset() {
this.clear_timer();
}
onDestroy() {
// 清理所有定时器
// console.log("[SkillConComp]:onDestroy:",this.node.name)
Object.values(this._timers).forEach(clearTimeout);
this._timers = {};
// 移除事件监听
this.off(GameEvent.CastHeroSkill);
}
}