Files
heros/assets/script/game/hero/SAutocastSystem.ts
walkpan 2f19433a0a feat(skill): 重构技能系统,新增技能数据组件和移动组件
refactor(skill): 移除旧技能组件和文档,优化技能配置结构

fix(skill): 修正技能预制体配置错误,统一技能运行类型字段

docs(skill): 删除过时的技能系统说明文档

perf(skill): 优化技能加载逻辑,减少资源消耗

style(skill): 调整代码格式,提高可读性
2025-10-31 00:35:51 +08:00

183 lines
6.0 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 { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { Vec3, v3 } from "cc";
import { CastSkillRequestComp } from "./STagComps";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { SkillSet, SType } from "../common/config/SkillSet";
import { HeroSkillsComp } from "./HeroSkills";
/**
* ==================== 自动施法系统 ====================
*
* 职责:
* 1. 检测可施放的技能
* 2. 根据策略自动施法AI
* 3. 选择目标
* 4. 添加施法请求标记
*
* 设计理念:
* - 负责"何时施法"的决策
* - 通过添加 CastSkillRequestComp 触发施法
* - 可被玩家输入系统或AI系统复用
* - 支持多种AI策略
*/
@ecs.register('SkillAutocastSystem')
export class SkillAutocastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
filter(): ecs.IMatcher {
return ecs.allOf(HeroSkillsComp, HeroAttrsComp, HeroViewComp);
}
update(e: ecs.Entity): void {
const skills = e.get(HeroSkillsComp);
const heroModel = e.get(HeroAttrsComp);
const heroView = e.get(HeroViewComp);
if (!skills || !heroModel || !heroView) return;
// 检查基本条件
if (heroModel.is_dead || heroModel.isStun() || heroModel.isFrost()) return;
// 检查是否正在攻击(只有攻击时才释放技能)
if (!heroModel.is_atking) return;
// 获取所有可施放的技能
const readySkills = skills.getReadySkills(heroModel.mp);
if (readySkills.length === 0) return;
// 选择第一个可施放的伤害技能
for (const skillIndex of readySkills) {
const skill = skills.getSkill(skillIndex);
if (!skill) continue;
const config = SkillSet[skill.uuid];
if (!config || config.SType !== SType.damage) continue;
// ✅ 添加施法请求标记组件
const request = e.add(CastSkillRequestComp) as CastSkillRequestComp;
request.skillIndex = skillIndex;
request.targetPositions = this.selectTargets(heroView);
// 一次只施放一个技能
break;
}
}
/**
* 选择目标位置
*/
private selectTargets(caster: HeroViewComp): Vec3[] {
// 简化版:选择最前方的敌人
const targets: Vec3[] = [];
// 这里可以调用 SkillConComp 的目标选择逻辑
// 暂时返回默认位置
const heroModel = caster.ent.get(HeroAttrsComp);
const fac = heroModel?.fac ?? 0;
const defaultX = fac === 0 ? 400 : -400;
targets.push(v3(defaultX, 0, 0));
return targets;
}
/**
* 选择伤害技能目标
*/
private selectDamageTargets(caster: HeroViewComp, config: any, maxTargets: number): Vec3[] {
const targets: Vec3[] = [];
const heroModel = caster.ent.get(HeroAttrsComp);
if (!heroModel) return targets;
// 寻找最近的敌人
const enemyPositions = this.findNearbyEnemies(caster, heroModel.fac, config.range || 300);
// 选择最多maxTargets个目标
for (let i = 0; i < Math.min(maxTargets, enemyPositions.length); i++) {
targets.push(enemyPositions[i]);
}
// 如果没有找到敌人,使用默认位置
if (targets.length === 0) {
targets.push(...this.selectDefaultTargets(caster, heroModel.fac));
}
return targets;
}
/**
* 选择治疗技能目标
*/
private selectHealTargets(caster: HeroViewComp, config: any, maxTargets: number): Vec3[] {
const targets: Vec3[] = [];
const heroModel = caster.ent.get(HeroAttrsComp);
if (!heroModel) return targets;
// 寻找血量最低的友军
const allyPositions = this.findLowHealthAllies(caster, heroModel.fac, config.range || 200);
for (let i = 0; i < Math.min(maxTargets, allyPositions.length); i++) {
targets.push(allyPositions[i]);
}
// 如果没有找到友军,治疗自己
if (targets.length === 0 && caster.node) {
targets.push(caster.node.position.clone());
}
return targets;
}
/**
* 选择BUFF技能目标
*/
private selectBuffTargets(caster: HeroViewComp, config: any, maxTargets: number): Vec3[] {
// BUFF技能通常施放在自己或友军身上
return this.selectHealTargets(caster, config, maxTargets);
}
/**
* 选择DEBUFF技能目标
*/
private selectDebuffTargets(caster: HeroViewComp, config: any, maxTargets: number): Vec3[] {
// DEBUFF技能通常施放在敌人身上
return this.selectDamageTargets(caster, config, maxTargets);
}
/**
* 选择默认目标
*/
private selectDefaultTargets(caster: HeroViewComp, faction: number): Vec3[] {
const targets: Vec3[] = [];
const defaultX = faction === 0 ? 400 : -400;
targets.push(v3(defaultX, 0, 0));
return targets;
}
/**
* 查找附近的敌人
*/
private findNearbyEnemies(caster: HeroViewComp, faction: number, range: number): Vec3[] {
// 简化实现实际应该查询ECS中的敌方实体
const enemies: Vec3[] = [];
// 模拟敌人位置
const enemyX = faction === 0 ? 300 : -300;
enemies.push(v3(enemyX, 0, 0));
enemies.push(v3(enemyX + 50, 20, 0));
return enemies;
}
/**
* 查找血量低的友军
*/
private findLowHealthAllies(caster: HeroViewComp, faction: number, range: number): Vec3[] {
// 简化实现实际应该查询ECS中的友方实体并按血量排序
const allies: Vec3[] = [];
// 如果自己血量低,优先治疗自己
return allies;
}
}