You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/script/battle/presentation/SkillPresenterRouter.ts

167 lines
6.0 KiB

3 weeks ago
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);
2 weeks ago
this.registerAtkType(16, lineMulti);
3 weeks ago
this.registerAtkType(15, instant);
this.registerAtkType(6, instant);
this.registerAtkType(7, instant);
this.registerAtkType(10, new SequentialSingleAtkPresenter());
this.registerAtkType(8, summon);
2 weeks ago
this.registerAtkType(11, summon);
3 weeks ago
const projectile = new ProjectileAtkPresenter();
this.registerAtkType(4, projectile);
this.registerAtkType(12, new ScatterPierceAtkPresenter());
2 weeks ago
this.registerAtkType(17, new ScatterPierceAtkPresenter());
3 weeks ago
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;
}
}