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.
89 lines
3.6 KiB
89 lines
3.6 KiB
import { Vec3 } from 'cc';
|
|
import { schedulePresentation } from '../../battle/skill/BattlePresentationClock';
|
|
import { BattleBuffCarryStore } from '../../manager/battleBuff/BattleBuffCarryStore';
|
|
import { rollCarriedKillPeachBonus } from '../../manager/battleBuff/BattleBuffPassiveSkillUtil';
|
|
import type { EntityId } from 'db://assets/mx/module/battle';
|
|
import type { CocosBagBoardView } from '../../battle/view/CocosBagBoardView';
|
|
import type { ProjectBattleHandle } from '../../battle/runtime/BattleRuntime';
|
|
import type { BattlePeachCoinFlyPresenter } from './BattlePeachCoinFlyPresenter';
|
|
|
|
/**
|
|
* 武财神(functiontype=25):本机击杀小怪概率额外蟠桃(飞币表现)。
|
|
* AI 侧额外桃在 BattleRuntime 直接入账,不走本 Presenter。
|
|
*/
|
|
export class BattleGameKillPeachPresenter {
|
|
private _battle: ProjectBattleHandle | null = null;
|
|
private _bagView: CocosBagBoardView | null = null;
|
|
private _peachFly: BattlePeachCoinFlyPresenter | null = null;
|
|
private _resolveDeathWorldPos: ((victim: EntityId) => Vec3 | null) | null = null;
|
|
/** 并行倒计时世代(unbind 时递增以作废待触发回调) */
|
|
private _scheduleGen = 0;
|
|
|
|
/** 绑定战斗、背包与死亡坐标解析 */
|
|
bind(
|
|
battle: ProjectBattleHandle | null,
|
|
bagView: CocosBagBoardView | null,
|
|
peachFly: BattlePeachCoinFlyPresenter | null,
|
|
resolveDeathWorldPos: (victim: EntityId) => Vec3 | null,
|
|
): void {
|
|
this.unbind();
|
|
this._battle = battle;
|
|
this._bagView = bagView;
|
|
this._peachFly = peachFly;
|
|
this._resolveDeathWorldPos = resolveDeathWorldPos;
|
|
}
|
|
|
|
/** 注销并中断进行中的演出 */
|
|
unbind(): void {
|
|
this._scheduleGen++;
|
|
this._battle = null;
|
|
this._bagView = null;
|
|
this._peachFly = null;
|
|
this._resolveDeathWorldPos = null;
|
|
}
|
|
|
|
/**
|
|
* 击杀回调:仅本机归属时掷骰;小怪且概率成功时逐枚产桃。
|
|
* @param killer 击杀者
|
|
* @param victim 死亡实体
|
|
*/
|
|
onEntityKilled(killer: EntityId, victim: EntityId): void {
|
|
const battle = this._battle;
|
|
const bagView = this._bagView;
|
|
const peachFly = this._peachFly;
|
|
const resolvePos = this._resolveDeathWorldPos;
|
|
if (!battle || !bagView || !peachFly || !resolvePos) return;
|
|
if (!battle.isSmallMonsterVictim(victim)) return;
|
|
const ownerId = battle.resolveKillPeachOwnerPlayerId(killer, victim);
|
|
if (ownerId !== battle.localPlayerId) return;
|
|
|
|
const peachCount = rollCarriedKillPeachBonus(BattleBuffCarryStore.getPassives(ownerId));
|
|
if (peachCount <= 0) return;
|
|
|
|
const startWorld = resolvePos(victim);
|
|
if (!startWorld) {
|
|
console.log('[KillPeach] 击杀额外蟠桃无死亡坐标', victim);
|
|
return;
|
|
}
|
|
|
|
this._playBonusPeachSequence(startWorld, peachCount);
|
|
}
|
|
|
|
/** 死亡点逐枚弹出 coinFly;枚间间隔 = 本次枚数(秒) */
|
|
private _playBonusPeachSequence(startWorld: Readonly<Vec3>, peachCount: number): void {
|
|
const bagView = this._bagView;
|
|
const peachFly = this._peachFly;
|
|
if (!bagView || !peachFly) return;
|
|
|
|
const intervalSec = peachCount;
|
|
const scheduleGen = ++this._scheduleGen;
|
|
for (let i = 0; i < peachCount; i++) {
|
|
const delay = i * intervalSec;
|
|
schedulePresentation(delay, () => {
|
|
if (scheduleGen !== this._scheduleGen) return;
|
|
peachFly.playKillDrop(startWorld, 1);
|
|
bagView.grantBattlePeach(1);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|