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.

115 lines
3.7 KiB

3 weeks ago
import { ChapterNewPlayTypeEnum, ICharmProperty } from '../../../game/ChapterPlayTypes';
import { cloneCharmConfig } from '../MechanismConfigClone';
import type { IBattleMechanism, MechanismContext } from '../IBattleMechanism';
import {
isCombatPhase,
pickRandomCharmTargets,
pickRandomDigGrid,
playFoxSpiritCharmVisual,
} from '../MechanismServices';
/** 狐狸精魅惑机制(Playmode 21) */
export class CharmMechanism implements IBattleMechanism {
readonly typeId = ChapterNewPlayTypeEnum.Charm;
private _ctx: MechanismContext | null = null;
private _config: ICharmProperty | null = null;
private _eventIndex = 0;
private _checkTimer = 0;
private _visualPending = 0;
init(ctx: MechanismContext, config: unknown): void {
this._ctx = ctx;
this._config = cloneCharmConfig(config as ICharmProperty);
this._eventIndex = 0;
this._checkTimer = 0;
this._visualPending = 0;
const cfg = this._config;
if (!cfg?.timeArr?.length) {
console.error('[CharmMechanism] 配表 timeArr 为空,机制不会触发');
return;
}
}
tick(dt: number): void {
if (!this._ctx || !this._config || !isCombatPhase(this._ctx)) return;
if (this._visualPending > 0) return;
this._checkTimer += dt;
if (this._checkTimer < 1) return;
this._checkTimer = 0;
this._tryTriggerDueEvents();
}
destroy(): void {
this._visualPending = 0;
this._ctx = null;
this._config = null;
this._eventIndex = 0;
}
private _tryTriggerDueEvents(): void {
const ctx = this._ctx;
const cfg = this._config;
if (!ctx || !cfg) return;
while (this._eventIndex < cfg.timeArr.length && ctx.battleTime >= cfg.timeArr[this._eventIndex]) {
if (!this._tryTriggerOnce()) break;
this._eventIndex++;
break;
}
}
private _tryTriggerOnce(): boolean {
const ctx = this._ctx;
const cfg = this._config;
if (!ctx || !cfg) return false;
const wave = this._eventIndex;
const targetCount = cfg.numArr[wave] ?? 1;
const rawDuration = cfg.durationArr[wave];
const durationSec = (typeof rawDuration === 'number' && Number.isFinite(rawDuration) && rawDuration > 0)
? rawDuration
: 2;
const exclude = ctx.runtime.charmController.getCharmedComposeKeys();
const targets = pickRandomCharmTargets(ctx, targetCount, exclude);
if (targets.length === 0) {
console.log(
'[CharmMechanism] 无可用魅惑目标(需地图上有已激活攻击的武器/英雄),event=',
wave,
'battleTime=',
ctx.battleTime,
'deployed=',
ctx.runtime.getPlayer(0)?.deployedUnits.length ?? 0,
);
return false;
}
let pending = 0;
for (const target of targets) {
const appearGrid = pickRandomDigGrid(ctx);
if (!appearGrid) {
console.log('[CharmMechanism] 无可开挖出现落点,target=', target.composeKey);
continue;
}
const ok = playFoxSpiritCharmVisual(
ctx,
appearGrid,
target,
durationSec,
ctx.runtime.charmController,
() => this._onVisualComplete(),
);
if (ok) pending++;
}
if (pending <= 0) return false;
this._visualPending = pending;
return true;
}
private _onVisualComplete(): void {
if (this._visualPending <= 0) return;
this._visualPending--;
}
}