Files
pixelheros/assets/script/game/hero/SkillTriggerHelper.ts
walkpan fd60191324 refactor(skill): 调整技能触发枚举的存放位置与使用方式
将SkillTriggerType枚举从GameEvent.ts迁移到heroSet.ts,统一管理技能触发相关配置,同时更新所有引用该枚举的文件路径,优化代码结构与维护性
2026-05-24 23:38:09 +08:00

157 lines
6.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 { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { SkillTriggerType } from "../common/config/heroSet";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { FacSet } from "../common/config/GameSet";
import { FieldSkillType, SkillOverrides } from "../common/config/SkillSet";
import { TalentType } from "../common/config/TalentSet";
import { smc } from "../common/SingletonModuleComp";
import { FieldSkillHelper } from "./FieldSkillHelper";
/**
* 特殊触发技能的统一中介者 (Mediator)
*
* 核心职责:
* 1. 统一管理英雄/怪物的各类生命周期触发技能(召唤、死亡、战前、战后、攻受击)。
* 2. 集中处理触发次数的计算(如:局内羁绊加成、局外天赋加成)。
* 3. 作为唯一出口,通过事件总线向 SCastSystem 派发 GameEvent.TriggerSkill 事件。
*
* 优势:
* - 极大地解耦了具体业务组件Hero/Mon/HeroAtkSystem/MissionComp与技能系统。
* - 避免了原先散落在各处的判定逻辑和冗余的事件派发代码。
*/
export class SkillTriggerHelper {
/**
* 统一的技能触发入口
* 根据传入的触发类型,自动分发到对应的处理函数中执行判定和加成逻辑。
*
* @param type 触发类型枚举 (SkillTriggerType)
* @param model 施法者的属性数据组件 (HeroAttrsComp)
* @param view 施法者的视图表现组件 (HeroViewComp)
*/
public static trigger(type: SkillTriggerType, model: HeroAttrsComp, view: HeroViewComp) {
// 健壮性检查:若实体或节点已被销毁,直接阻断,防止空指针报错
if (!model || !view || !view.node || !view.node.isValid) return;
switch (type) {
case SkillTriggerType.Call:
this.handleCall(model, view);
break;
case SkillTriggerType.Dead:
this.handleDead(model, view);
break;
case SkillTriggerType.FStart:
this.handleArrayTrigger(model.fstart, model, view, type);
break;
case SkillTriggerType.FEnd:
this.handleArrayTrigger(model.fend, model, view, type);
break;
case SkillTriggerType.Atking:
this.handleAtking(model, view);
break;
case SkillTriggerType.Atked:
this.handleAtked(model, view);
break;
}
}
/**
* 处理召唤(落地)触发技能
* 支持受【召唤强化羁绊 (SummonCount)】和【召唤强化天赋 (TalentType.Summon)】的多次触发加成。
*/
private static handleCall(model: HeroAttrsComp, view: HeroViewComp) {
if (!model.call || model.call.length === 0) return;
let triggerCount = 1;
// 仅英雄享受加成,怪物始终只触发 1 次
if (model.fac === FacSet.HERO) {
triggerCount += FieldSkillHelper.getFieldSkillTotalValue(FieldSkillType.SummonCount);
triggerCount += HeroAttrsComp.getTalentValue(TalentType.Summon);
}
triggerCount = Math.max(1, Math.floor(triggerCount)); // 确保最少触发 1 次
for (let i = 0; i < triggerCount; i++) {
this.dispatchArray(model.call, model, view, SkillTriggerType.Call);
}
}
/**
* 处理死亡触发技能
* 支持受【亡语强化羁绊 (DeadCount)】的多次触发加成。
*/
private static handleDead(model: HeroAttrsComp, view: HeroViewComp) {
if (!model.dead || model.dead.length === 0) return;
let triggerCount = 1;
if (model.fac === FacSet.HERO) {
triggerCount += FieldSkillHelper.getFieldSkillTotalValue(FieldSkillType.DeadCount);
// 【局内战绩评分系统】统计死亡触发技能生效次数(用于局后防守评分结算)
smc.vmdata.scores.dead_trigger_count += model.dead.length;
}
triggerCount = Math.max(1, Math.floor(triggerCount));
for (let i = 0; i < triggerCount; i++) {
this.dispatchArray(model.dead, model, view, SkillTriggerType.Dead);
}
}
/**
* 处理攻击附加技能
* 判定逻辑:依据配置中的 t_num触发所需普攻次数对比当前的普攻累计次数取模判定。
*/
private static handleAtking(model: HeroAttrsComp, view: HeroViewComp) {
if (!model.atking || model.atking.length === 0) return;
model.atking.forEach(atkConfig => {
// atk_count 代表已进行的普攻次数。当其余数刚好整除配置阈值时触发。
if (model.atk_count > 0 && model.atk_count % atkConfig.t_num === 0) {
this.dispatchSingle(atkConfig.s_uuid, model, view, SkillTriggerType.Atking, atkConfig.overrides);
}
});
}
/**
* 处理受击附加技能
* 判定逻辑:依据配置中的 t_num触发所需受击次数对比当前的受击累计次数取模判定。
*/
private static handleAtked(model: HeroAttrsComp, view: HeroViewComp) {
if (!model.atked || model.atked.length === 0) return;
model.atked.forEach(atkConfig => {
// atked_count 代表已承受的受击次数。当其余数刚好整除配置阈值时触发。
if (model.atked_count > 0 && model.atked_count % atkConfig.t_num === 0) {
this.dispatchSingle(atkConfig.s_uuid, model, view, SkillTriggerType.Atked, atkConfig.overrides);
}
});
}
/**
* 通用的数组型触发器处理(适用于 FStart / FEnd 等无需额外判定的简单列表触发)
*/
private static handleArrayTrigger(configs: {s_uuid: number, t_num: number, overrides?: SkillOverrides}[] | undefined, model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType) {
if (!configs || configs.length === 0) return;
this.dispatchArray(configs, model, view, type);
}
/**
* 批量派发技能事件
*/
private static dispatchArray(configs: {s_uuid: number, t_num?: number, overrides?: SkillOverrides}[], model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType) {
configs.forEach(config => this.dispatchSingle(config.s_uuid, model, view, type, config.overrides));
}
/**
* 单一技能事件派发底层接口
* 事件发出后,将由 SCastSystem 的 forceCastTriggerSkill 监听拦截并执行无视CD的强制施法
*/
private static dispatchSingle(s_uuid: number, model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType, overrides?: SkillOverrides) {
oops.message.dispatchEvent(GameEvent.TriggerSkill, {
s_uuid: s_uuid,
heroAttrs: model,
heroView: view,
triggerType: type,
overrides: overrides
});
}
}