refactor(英雄技能): 重构技能系统以支持多技能和独立冷却
- 将 HeroAttrsComp 中的单一攻击/技能ID重构为技能数组,支持多个技能 - 为每个技能添加独立的冷却计时和最大冷却时间 - 修改 SCastSystem 以支持多技能选择和冷却检查 - 更新 HeroViewComp 显示当前展示技能的冷却进度 - 统一英雄和怪物初始化技能的方式,使用 setSkills 方法 - 移除 heroSet 配置中的 as/ss 字段,改为 cds 数组 - 修改 Skill 实体加载,传递 HeroAttrsComp 用于技能伤害计算
This commit is contained in:
@@ -56,15 +56,13 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const type = heroAttrs.type as HType;
|
||||
const maxRange = this.resolveMaxCastRange(heroAttrs, type);
|
||||
const target = this.findNearestEnemyInRange(heroAttrs, heroView, maxRange);
|
||||
const skillCandidates = [heroAttrs.skill_id, heroAttrs.atk_id];
|
||||
const skillCandidates = this.buildSkillCandidates(heroAttrs.getSkillIds());
|
||||
const selfEid = heroView.ent?.eid;
|
||||
for (const s_uuid of skillCandidates) {
|
||||
if (!s_uuid) continue;
|
||||
const config = SkillSet[s_uuid];
|
||||
if (!config) continue;
|
||||
const isMainSkill = s_uuid === heroAttrs.skill_id;
|
||||
if (isMainSkill && !heroAttrs.can_skill) continue;
|
||||
if (!isMainSkill && !heroAttrs.can_atk) continue;
|
||||
if (!heroAttrs.isSkillReady(s_uuid)) continue;
|
||||
if (this.isSelfSkill(config.TGroup)) {
|
||||
if (typeof selfEid !== "number") continue;
|
||||
return { skillId: s_uuid, isFriendly: true, targetPos: null, targetEids: [selfEid] };
|
||||
@@ -91,8 +89,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
heroView.playReady(config.readyAnm);
|
||||
//播放角色攻击动画
|
||||
heroView.playSkillAnm(config.act);
|
||||
const isMainSkill = s_uuid === heroAttrs.skill_id;
|
||||
|
||||
|
||||
// 优先使用技能配置的前摇时间,否则使用全局默认值
|
||||
// 注意:这里仍然是基于时间的延迟,受帧率波动影响。
|
||||
// 若需精确同步,建议在动画中添加帧事件并在 HeroViewComp 中监听。
|
||||
@@ -103,32 +100,34 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (castPlan.isFriendly) {
|
||||
const friendlyTargets = this.resolveFriendlyTargets(castPlan.targetEids, heroAttrs.fac);
|
||||
if (friendlyTargets.length === 0) return;
|
||||
this.applyPrimaryEffect(s_uuid, config, heroView, friendlyTargets, null);
|
||||
this.applyPrimaryEffect(s_uuid, config, heroView,heroAttrs, friendlyTargets, null);
|
||||
this.applyExtraEffects(config, friendlyTargets);
|
||||
return;
|
||||
}
|
||||
this.applyPrimaryEffect(s_uuid, config, heroView, [], castPlan.targetPos);
|
||||
this.applyPrimaryEffect(s_uuid, config, heroView,heroAttrs, [], castPlan.targetPos);
|
||||
}, delay);
|
||||
if (isMainSkill) {
|
||||
heroAttrs.triggerSkillCD();
|
||||
} else {
|
||||
heroAttrs.triggerAtkCD();
|
||||
}
|
||||
heroAttrs.triggerSkillCD(s_uuid);
|
||||
}
|
||||
|
||||
private createSkillEntity(s_uuid: number, caster: HeroViewComp, targetPos: Vec3) {
|
||||
private buildSkillCandidates(skillIds: number[]): number[] {
|
||||
if (!skillIds || skillIds.length === 0) return [];
|
||||
if (skillIds.length === 1) return [skillIds[0]];
|
||||
return [...skillIds.slice(1), skillIds[0]];
|
||||
}
|
||||
|
||||
private createSkillEntity(s_uuid: number, caster: HeroViewComp,cAttrsComp: HeroAttrsComp, targetPos: Vec3) {
|
||||
if (!caster.node || !caster.node.isValid) return;
|
||||
const parent = caster.node.parent;
|
||||
if (!parent) return;
|
||||
const skill = ecs.getEntity<Skill>(Skill);
|
||||
skill.load(caster.node.position.clone(), parent, s_uuid, targetPos.clone(), caster, 0);
|
||||
skill.load(caster.node.position.clone(), parent, s_uuid, targetPos.clone(), caster,cAttrsComp, 0);
|
||||
}
|
||||
|
||||
private applyPrimaryEffect(s_uuid: number, config: SkillConfig, heroView: HeroViewComp, targets: HeroViewComp[], targetPos: Vec3 | null) {
|
||||
private applyPrimaryEffect(s_uuid: number, config: SkillConfig, heroView: HeroViewComp, cAttrsComp: HeroAttrsComp,targets: HeroViewComp[], targetPos: Vec3 | null) {
|
||||
const kind = config.kind ?? SkillKind.Damage;
|
||||
if (kind === SkillKind.Damage) {
|
||||
if (config.ap <= 0 || !targetPos) return;
|
||||
this.createSkillEntity(s_uuid, heroView, targetPos);
|
||||
this.createSkillEntity(s_uuid, heroView,cAttrsComp, targetPos);
|
||||
return;
|
||||
}
|
||||
for (const target of targets) {
|
||||
|
||||
Reference in New Issue
Block a user