Files
heros/assets/script/game/hero/SkillConComp.ts
2025-06-06 16:26:13 +08:00

142 lines
5.6 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, Vec3 } from 'cc';
import { HeroViewComp } from './HeroViewComp';
import { SkillSet, TargetGroup, TargetType } from '../common/config/SkillSet';
import { Skill } from '../skills/Skill';
import { ecs } from 'db://oops-framework/libs/ecs/ECS';
import { oops } from 'db://oops-framework/core/Oops';
import { GameEvent } from '../common/config/GameEvent';
import { BoxSet } from '../common/config/BoxSet';
import { smc } from '../common/SingletonModuleComp';
import { CCComp } from 'db://oops-framework/module/common/CCComp';
const { ccclass, property } = _decorator;
@ccclass('SkillCon')
@ecs.register('SkillCon')
export class SkillConComp extends CCComp {
HeroView:any=null;
HeroEntity:any=null;
private _timers: { [key: string]: number } = {};
private _damageQueue: Array<{ timer: number; callback: () => void }> = [];
init(): void {
oops.message.on(GameEvent.FightEnd, this.clear_timer, this);
}
onLoad(){
this.HeroView=this.node.getComponent(HeroViewComp)
// console.log(this.HeroView.uuid+"=>"+this.HeroView.hero_name+"=> SkillConComp onLoad")
this.on(GameEvent.CastHeroSkill,this.cast_master_skill,this)
}
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.is_atking &&this.HeroView.at > this.HeroView.cd) {
const config = SkillSet[this.HeroView.atk_skill];
if (!config) return;
this.castSkill(config);
this.HeroView.at = 0;
}
}
cast_master_skill(e:string,uuid:any){
if(!this.HeroView) return
if(!this.HeroView.is_master) return
console.log("hart cast_skill",uuid ,e)
const config = SkillSet[uuid];
this.castSkill(config)
}
/** 施放技能 */
castSkill(config: typeof SkillSet[keyof typeof SkillSet]) {
// console.log(view.uuid+"=>"+view.hero_name+"施放技能:"+config.uuid);
if (config.TargetGroup === TargetGroup.Enemy) {
this.HeroView.playSkillEffect(config.uuid);
this.doSkill(config);
}
if (config.TargetGroup === TargetGroup.Ally) {
const targets = this.selectAllyTargets( config);
if (targets.length === 0) return;
}
if (config.TargetGroup === TargetGroup.Self) {
}
}
private doSkill(config: typeof SkillSet[keyof typeof SkillSet]) {
const skillEntity = ecs.getEntity<Skill>(Skill);
const targets = this.selectEnemyTargets(config);
if (targets.length === 0) return;
skillEntity.load(
new Vec3(this.HeroView.node.position.x, this.HeroView.node.position.y+BoxSet.ATK_Y, 0), // 起始位置
this.HeroView.box_group, // 阵营
this.node.parent, // 父节点
config.uuid, // 技能ID
new Vec3(targets[0]?.get(HeroViewComp).node.position.x, targets[0]?.get(HeroViewComp).node.position.y, 0), // 目标位置
this.HeroView
);
// console.log("技能:"+config.uuid+"=>"+targets[0]?.get(HeroViewComp).hero_name);
}
private selectEnemyTargets(config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
const team = this.HeroView.fac;
const isEnemyTeam = team === 0 ? 1 : 0;
const candidates= ecs.query(ecs.allOf(HeroViewComp)).filter(e => e.get(HeroViewComp).fac !== team);
return this.filterFrontRow(candidates, isEnemyTeam);
}
/** 筛选最前排单位 */
private filterFrontRow(entities: ecs.Entity[], isEnemyTeam: number): ecs.Entity[] {
// 敌方最前排是x坐标最大的我方最前排是x坐标最小的
const keyPos = isEnemyTeam ?
Math.min(...entities.map(e => e.get(HeroViewComp).node.position.x)) :
Math.max(...entities.map(e => e.get(HeroViewComp).node.position.x));
return entities.filter(e =>
Math.abs(e.get(HeroViewComp).node.position.x - keyPos) < 10
);
}
private selectAllyTargets( config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
const team = this.HeroView.fac;
const candidates= ecs.query(ecs.allOf(HeroViewComp)).filter(e => e.get(HeroViewComp).fac === team);
// 第二阶段:位置/血量等精细筛选
switch(config.TargetType) {
case TargetType.Melee:
return candidates.filter(e => e.get(HeroViewComp).type === 0);
case TargetType.Ranged:
return candidates.filter(e => e.get(HeroViewComp).type === 1);
case TargetType.SupportClass:
return candidates.filter(e => e.get(HeroViewComp).type === 2);
case TargetType.Random:
return this.pickRandomTarget(candidates, config.count || 1);
default:
return candidates;
}
}
/** 随机选择目标 */
private pickRandomTarget(entities: ecs.Entity[], count: number): ecs.Entity[] {
const shuffled = [...entities].sort(() => 0.5 - Math.random());
return shuffled.slice(0, count);
}
public clear_timer() {
// console.log("clear_timer");
Object.values(this._timers).forEach(clearTimeout);
}
reset() {
this.clear_timer();
}
onDestroy() {
// console.log("SkillConComp onDestroy")
Object.values(this._timers).forEach(clearTimeout);
}
}