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/combat/BattleBuffUnitLevelUpApply.ts

131 lines
5.8 KiB

3 weeks ago
import type { EntityId } from 'db://assets/mx/module/ecs';
import { TableNames } from '../../game/ConfigTableData';
import type { BattleBagSession } from '../bag/BattleBagSession';
import { WeaponComposeConfigProvider } from '../bag/WeaponComposeConfigProvider';
import { findEntityIdByGridIndex } from '../runtime/DeployEntityQuery';
import type { ProjectBattleHandle } from '../runtime/BattleRuntime';
import type { BattleBuffSkillDropTarget } from '../view/CocosBagBoardView';
import { getTowerExpHost, needTowerExpForLevel } from './TowerExpHost';
import { getTowerLoadoutService } from './TowerLoadoutService';
/**
* 封神榜(functiontype=2)/ 授仙箓(functiontype=7):
* 多格组合字武将、普通 type1 单字(含已上场单字塔)可施放;type2 未合成英雄散字不可。
* 攻速符/千里眼等拖到字块类主动 buff 共用 MergeSession.canApplyBattleBuffSkillDrop* 落点校验。
* 对已部署多格合成武将升级时补剩余经验;授仙箓降级时清空累计经验。
*/
/** 是否地图多格合成武将(已部署时走补经验) */
export function isBattleBuffLevelUpExpFillMapTarget(bagSession: BattleBagSession, gridIndex: number): boolean {
return bagSession.merge.isMultiCellCompositionAt(gridIndex);
}
/** 地图格 → 已部署塔实体;未部署则 null */
export function resolveBattleBuffLevelUpMapEntity(
battle: ProjectBattleHandle,
bagSession: BattleBagSession,
gridIndex: number,
): EntityId | null {
const map = battle.Map;
const player = battle.getPlayer(bagSession.ownerPlayerId);
if (!map || !player) return null;
const entityId = findEntityIdByGridIndex(gridIndex, battle.session, map, player);
if (entityId == null || !battle.session.world.isAlive(entityId)) return null;
return entityId;
}
/** 是否应对该落点走「补剩余升级经验」 */
export function shouldBattleBuffLevelUpViaExpFill(
battle: ProjectBattleHandle | null,
bagSession: BattleBagSession,
target: BattleBuffSkillDropTarget,
): boolean {
if (target.kind !== 'map' || !battle) return false;
if (!isBattleBuffLevelUpExpFillMapTarget(bagSession, target.gridIndex)) return false;
return resolveBattleBuffLevelUpMapEntity(battle, bagSession, target.gridIndex) != null;
}
/** 授仙箓降级:是否须清空已部署多格合成武将经验 */
export function shouldBattleBuffLevelDownClearExp(
battle: ProjectBattleHandle,
bagSession: BattleBagSession,
target: BattleBuffSkillDropTarget,
): boolean {
return shouldBattleBuffLevelUpViaExpFill(battle, bagSession, target);
}
/** 授仙箓降级:清空已部署多格合成武将累计经验 */
export function applyBattleBuffLevelDownClearExp(
battle: ProjectBattleHandle,
bagSession: BattleBagSession,
gridIndex: number,
): void {
const entityId = resolveBattleBuffLevelUpMapEntity(battle, bagSession, gridIndex);
if (entityId == null) return;
getTowerExpHost().clearExp(entityId);
}
/** 已部署多格合成武将:是否可补剩余升级经验 */
export function canApplyBattleBuffLevelUpViaExpFill(
battle: ProjectBattleHandle,
bagSession: BattleBagSession,
gridIndex: number,
levelDelta: number,
): boolean {
if (levelDelta <= 0) return false;
if (bagSession.merge.canApplyBattleBuffUnitLevelUp(gridIndex, levelDelta) != null) return false;
const entityId = resolveBattleBuffLevelUpMapEntity(battle, bagSession, gridIndex);
if (entityId == null) return false;
const loadout = getTowerLoadoutService().getLoadout(entityId);
if (!loadout) return false;
const hero = gg.data.table.getTableData<ITableHero>(TableNames.Hero, loadout.weapon1Id);
if (!hero) return false;
const max = WeaponComposeConfigProvider.instance.getMaxWeaponLevel(loadout.weapon1Id);
if (loadout.level >= max) return false;
return needTowerExpForLevel(hero, loadout.level) > 0;
}
/** 已部署多格合成武将:补剩余升级经验(可触发正常经验升级) */
export function applyBattleBuffLevelUpViaExpFill(
battle: ProjectBattleHandle,
bagSession: BattleBagSession,
gridIndex: number,
): boolean {
const entityId = resolveBattleBuffLevelUpMapEntity(battle, bagSession, gridIndex);
if (entityId == null) return false;
return getTowerExpHost().grantRemainingExpForNextLevel(battle, entityId);
}
/**
* 授仙箓:掷骰并写盘;已部署合成武将若掷到升级则补剩余经验。
* @param rollWan 0~9999
*/
export function applyBattleBuffRandomLevelWithExpFill(
battle: ProjectBattleHandle,
bagSession: BattleBagSession,
target: BattleBuffSkillDropTarget,
levelUpProbsWan: readonly number[],
rollWan: number,
): number | null {
const merge = bagSession.merge;
if (target.kind === 'map') {
const rolled = merge.rollBattleBuffRandomLevelMap(target.gridIndex, levelUpProbsWan, rollWan);
if (typeof rolled !== 'number') return null;
if (rolled > 0 && shouldBattleBuffLevelUpViaExpFill(battle, bagSession, target)) {
if (canApplyBattleBuffLevelUpViaExpFill(battle, bagSession, target.gridIndex, rolled)) {
return applyBattleBuffLevelUpViaExpFill(battle, bagSession, target.gridIndex) ? rolled : null;
}
}
const result = merge.applyBattleBuffRandomLevelMapDelta(target.gridIndex, rolled);
if (typeof result === 'number' && result < 0 && shouldBattleBuffLevelDownClearExp(battle, bagSession, target)) {
applyBattleBuffLevelDownClearExp(battle, bagSession, target.gridIndex);
}
return typeof result === 'number' ? result : null;
}
const rolled = merge.rollBattleBuffRandomLevelBag(target.slotIndex, levelUpProbsWan, rollWan);
if (typeof rolled !== 'number') return null;
const result = merge.applyBattleBuffRandomLevelBagDelta(target.slotIndex, rolled);
return typeof result === 'number' ? result : null;
}