Files
heros/assets/script/game/hero/SkillConComp.ts

182 lines
6.1 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, Component, Node, ProgressBar, v3, Vec3 } from 'cc';
import { HeroViewComp } from './HeroViewComp';
import { 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 { HeroAttrsComp } from './HeroAttrsComp';
import { HeroSkillsComp } from './HeroSkills';
import { CastSkillRequestComp } from './HSkillSystem';
import { SkillEnt } from '../skill/SkillEnt';
import { Attrs } from '../common/config/HeroAttrs';
import { TalComp } from './TalComp';
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)
}
start() {
this.HeroEntity=this.HeroView.ent
}
/**
* ⚠️ 注意:此方法已废弃
* 技能CD更新和施法逻辑已迁移到 HSkillSystemSkillCDSystem + SkillAutocastSystem
* 保留此方法仅用于手动触发技能(如玩家点击技能按钮)
*/
update(dt: number) {
// 已由 SkillCDSystem 和 SkillAutocastSystem 处理
// 此方法可以删除或改为手动施法的入口
}
/**
* 手动施放技能(玩家点击技能按钮)
* @param skillIndex 技能索引
*/
manualCastSkill(skillIndex: number) {
if (!this.HeroEntity) return;
// 选择目标
const targets = this.selectTargets(1);
// ✅ 通过添加标记组件请求施法
const request = this.HeroEntity.add(CastSkillRequestComp) as CastSkillRequestComp;
request.skillIndex = skillIndex;
request.targetPositions = targets;
}
/** 施放技能 */
castSkill(config: typeof SkillSet[keyof typeof SkillSet]) {
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.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(HeroAttrsComp))
}else{
return ecs.query(ecs.allOf(HeroAttrsComp))
}
}
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);
}
}