Files
heros/assets/script/game/skill/HeroSkillSystem.ts
2025-03-26 16:57:15 +08:00

147 lines
5.9 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 { Node, Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { HeroViewComp } from "../hero/HeroViewComp";
import { SkillSet, TargetGroup, TargetType } from "../common/config/SkillSet";
import { CdType } from "../common/config/SkillSet";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { Skill } from "../skills/Skill";
import { SkillCom } from "../skills/SkillCom";
import { AnimType } from "../common/config/SkillSet";
/** 技能系统 */
@ecs.register('HeroSkillSystem')
export class HeroSkillSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
// export class HeroSkillSystem implements ecs.ISystemUpdate {
// private updateInterval: number = 0.1; // 每0.1秒更新一次
// private accumulator: number = 0;
private _timers: { [key: string]: number } = {};
private _damageQueue: Array<{ timer: number; callback: () => void }> = [];
init(): void {
oops.message.on(GameEvent.MissionEnd, this.clear_timer, this);
}
filter(): ecs.IMatcher {
return ecs.allOf(HeroViewComp);
}
update(e: ecs.Entity) {
//return false
// 处理伤害队列
const view = e.get(HeroViewComp);
// 只在攻击状态触发技能
if (view.is_atking &&view.at > view.cd) {
const config = SkillSet[view.atk_skill];
if (!config) return;
this.castSkill(e, view.atk_skill, config);
view.at = 0;
}
}
/** 施放技能 */
private castSkill(caster: ecs.Entity, skillId: number, config: typeof SkillSet[keyof typeof SkillSet]) {
const view = caster.get(HeroViewComp);
const skillEntity = ecs.getEntity<Skill>(Skill);
console.log(view.hero_name+"施放技能:"+config.uuid+"=>"+view.hero_name);
if (config.TargetGroup === TargetGroup.Enemy) {
const targets = this.selectEnemyTargets(caster, config);
if (targets.length === 0) return;
skillEntity.load(
view.node.position, // 起始位置
view.box_group, // 阵营
view.node.parent, // 父节点
config.uuid, // 技能ID
targets[0]?.get(HeroViewComp).node.position, // 目标位置
targets[0]?.get(HeroViewComp),
view
);
targets.forEach(target => {
this.applySkillEffect(caster, target, config,skillEntity);
console.log("施放技能:"+config.uuid+"=>"+target.get(HeroViewComp).hero_name);
});
}
if (config.TargetGroup === TargetGroup.Ally) {
const targets = this.selectAllyTargets(caster, config);
if (targets.length === 0) return;
targets.forEach(target => {
this.applySkillEffect(caster, target, config,skillEntity);
});
}
if (config.TargetGroup === TargetGroup.Self) {
this.applySkillEffect(caster, caster, config,skillEntity);
}
}
private selectEnemyTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
const casterView = caster.get(HeroViewComp);
const team = casterView.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 selectAllyTargets(caster: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]): ecs.Entity[] {
const casterView = caster.get(HeroViewComp);
const team = casterView.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 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 pickRandomTarget(entities: ecs.Entity[], count: number): ecs.Entity[] {
const shuffled = [...entities].sort(() => 0.5 - Math.random());
return shuffled.slice(0, count);
}
/** 应用技能效果 */
private applySkillEffect(caster: ecs.Entity, target: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet],skillEntity:ecs.Entity) {
const casterView = caster.get(HeroViewComp);
// 播放技能特效
casterView.playSkillEffect(config.uuid);
}
public clear_timer() {
console.log("clear_timer");
Object.values(this._timers).forEach(clearTimeout);
}
onDestroy() {
Object.values(this._timers).forEach(clearTimeout);
}
/** 应用负面状态 */
private applyDebuff(target: ecs.Entity, config: typeof SkillSet[keyof typeof SkillSet]) {
// 实现debuff逻辑...
}
}