import type { Skill } from '../skill/Skill'; import type { SkillPresentationContext } from '../skill/SkillPresentationTypes'; import type { ISkillPresenter } from './SkillPresenter'; import { FallbackAtkPresenter, InstantAtkPresenter, LineMultiHitAtkPresenter, LineRectAtkPresenter, ProjectileAtkPresenter, ScatterPierceAtkPresenter, SequentialSingleAtkPresenter, SummonAtkPresenter, VolleyArrowAtkPresenter, } from './AtkTypePresenters'; /** * 技能表现路由:Skill.skill 额外效果头优先,其次 skillId,否则 atk_type。 * 三槽(普攻/英雄主动/武器主动)共用。 */ export class SkillPresenterRouter { private static _inst: SkillPresenterRouter | null = null; /** 单例 */ static get instance(): SkillPresenterRouter { if (!this._inst) { this._inst = new SkillPresenterRouter(); this._inst._registerBuiltin(); } return this._inst; } private readonly _bySkillId: { id: number; presenter: ISkillPresenter }[] = []; private readonly _byAtkType: { type: number; presenter: ISkillPresenter }[] = []; private readonly _byExtra: { type: number; presenter: ISkillPresenter }[] = []; private _fallback: ISkillPresenter = new FallbackAtkPresenter(); /** 按 skillId 注册特殊表现 */ registerSkillId(skillId: number, presenter: ISkillPresenter): void { const id = Math.floor(Number(skillId) || 0); if (id <= 0) { console.log('[SkillPresenterRouter] skillId 无效', skillId); return; } const idx = this._findSkillIndex(id); if (idx >= 0) this._bySkillId[idx].presenter = presenter; else this._bySkillId.push({ id, presenter }); } /** * 按 Skill.skill 头类型注册额外效果表现。 * @param extraType skill 字段第一段 * @param presenter 表现 */ registerExtraSkill(extraType: number, presenter: ISkillPresenter): void { const type = Math.floor(Number(extraType) || 0); if (type <= 0) { console.log('[SkillPresenterRouter] extraSkill 类型无效', extraType); return; } for (let i = 0; i < this._byExtra.length; i++) { if (this._byExtra[i].type === type) { this._byExtra[i].presenter = presenter; return; } } this._byExtra.push({ type, presenter }); } /** 按 atk_type 注册通用表现 */ registerAtkType(atkType: number, presenter: ISkillPresenter): void { const type = Math.floor(Number(atkType) || 0); const idx = this._findTypeIndex(type); if (idx >= 0) this._byAtkType[idx].presenter = presenter; else this._byAtkType.push({ type, presenter }); } /** 分发表现 */ dispatch(ctx: SkillPresentationContext, host: Skill): void { if (!ctx.isAlive) return; const extraRaw = String( ctx.params.extraSkill ?? (String(ctx.params.skillKind ?? '') === 'normal' ? '' : ctx.params.skillRaw) ?? '', ).trim(); if (extraRaw) { const extraHead = Math.floor(Number(extraRaw.split(',')[0]) || 0); const extraPres = this._findExtraPresenter(extraHead); if (extraPres) { extraPres.present(ctx, host); return; } } const skillId = Math.floor(Number(ctx.params.skillId ?? ctx.baseAtkId) || 0); const byId = this._findSkillPresenter(skillId); if (byId) { byId.present(ctx, host); return; } const atkHead = Math.floor(Number(ctx.params.atkTypeHead ?? ctx.params.atkType) || 0); const byType = this._findTypePresenter(atkHead); if (byType) { byType.present(ctx, host); return; } this._fallback.present(ctx, host); } private _registerBuiltin(): void { const instant = new InstantAtkPresenter(); const lineRect = new LineRectAtkPresenter(); const lineMulti = new LineMultiHitAtkPresenter(); const summon = new SummonAtkPresenter(); this.registerAtkType(1, instant); this.registerAtkType(2, lineRect); this.registerAtkType(3, instant); this.registerAtkType(5, lineMulti); this.registerAtkType(14, lineMulti); this.registerAtkType(16, lineMulti); this.registerAtkType(15, instant); this.registerAtkType(6, instant); this.registerAtkType(7, instant); this.registerAtkType(10, new SequentialSingleAtkPresenter()); this.registerAtkType(8, summon); this.registerAtkType(11, summon); const projectile = new ProjectileAtkPresenter(); this.registerAtkType(4, projectile); this.registerAtkType(12, new ScatterPierceAtkPresenter()); this.registerAtkType(17, new ScatterPierceAtkPresenter()); this.registerAtkType(13, new VolleyArrowAtkPresenter()); } private _findSkillIndex(id: number): number { for (let i = 0; i < this._bySkillId.length; i++) { if (this._bySkillId[i].id === id) return i; } return -1; } private _findTypeIndex(type: number): number { for (let i = 0; i < this._byAtkType.length; i++) { if (this._byAtkType[i].type === type) return i; } return -1; } private _findSkillPresenter(id: number): ISkillPresenter | null { const idx = this._findSkillIndex(id); return idx >= 0 ? this._bySkillId[idx].presenter : null; } private _findTypePresenter(type: number): ISkillPresenter | null { const idx = this._findTypeIndex(type); return idx >= 0 ? this._byAtkType[idx].presenter : null; } /** * 按 extra skill 头查找表现。 * @param type skill 第一段 */ private _findExtraPresenter(type: number): ISkillPresenter | null { for (let i = 0; i < this._byExtra.length; i++) { if (this._byExtra[i].type === type) return this._byExtra[i].presenter; } return null; } }