- 修改Hero和Monster类中技能对象,新增cost属性用于技能消耗 - 修复HeroViewComp中isStun和isFrost方法,确保返回布尔值 - SkillConComp日志输出技能列表和消耗信息,增强调试能力 - 更新英雄配置中的map属性值由0改为100,统一角色数据映射
179 lines
6.3 KiB
TypeScript
179 lines
6.3 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
|
|
console.log(this.HeroView.uuid+"=>"+this.HeroView.hero_name+"技能列表:",skills)
|
|
for(let i=0;i<skills.length;i++){
|
|
skills[i].cd += dt;
|
|
console.log(this.HeroView.uuid+"=>"+skills[i].cost,this.HeroView.mp)
|
|
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);
|
|
}
|
|
}
|
|
|
|
|