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/skill/GlobalSkillEffects.ts

148 lines
4.7 KiB

import type { BattleSession } from 'db://assets/mx/module/battle';
import {
AttributeComp,
BattleTeamId,
TeamComp,
TagComp,
EntityTag,
} from 'db://assets/mx/module/battle';
import type { EntityId } from 'db://assets/mx/module/ecs';
import { TableNames } from '../../game/ConfigTableData';
import { heroCharacterIds, isElementHero } from '../config/BattleHeroTable';
import { Weapon2TileType } from 'db://assets/mx/module/merge';
function _parseBaseAttr(raw: string): Array<{ type: number; value: number }> {
if (!raw) return [];
const out: Array<{ type: number; value: number }> = [];
for (const seg of raw.split(';')) {
const part = seg.trim();
if (!part) continue;
const [typeStr, valueStr] = part.split(',');
const type = Number(typeStr);
const value = Number(valueStr);
if (!Number.isFinite(type) || !Number.isFinite(value)) continue;
out.push({ type, value });
}
return out;
}
/** 全局词条:已删表字段,恒 false */
export function isGlobalSkillEntry(_entry: ITableSkill): boolean {
return false;
}
/** 物化到某武器塔:词条表已删,恒空 */
export function entriesAffectingWeapon(
_skills: readonly ITableSkill[],
_weapon1Id: number,
): ITableSkill[] {
return [];
}
/** 汇总已选词条 base_attr(词条已删,恒 0) */
export function sumSelectedBaseAttrWan(
skills: readonly ITableSkill[],
attrType: number,
): number {
let sum = 0;
for (const entry of skills) {
const raw = (entry as ITableSkill & { base_attr?: string }).base_attr ?? '';
for (const { type, value } of _parseBaseAttr(raw)) {
if (type === attrType) sum += value;
}
}
return sum;
}
/** 万分比加成 → 权重乘数:1000 → ×1.1 */
export function wanToWeightMul(wan: number): number {
if (wan <= 0) return 1;
return 1 + wan / 10000;
}
const GLOBAL_SLOW_SOURCE = 'global_skill_slow';
/**
* 怪物减速:base_attr type8,万分比减速量(1000=减速10%→移速×0.9)。
* 对单个敌人写入持久 Mul(无 remain)。
*/
export function applyGlobalMonsterSlowToEntity(
session: BattleSession,
entityId: EntityId,
slowWan: number,
): void {
if (slowWan <= 0) return;
const world = session.world;
if (!world.isAlive(entityId)) return;
if (!_isEnemy(world, entityId)) return;
if (!world.getComponent(entityId, AttributeComp)) {
world.addComponent(entityId, new AttributeComp());
}
const attrs = session.attributes;
const attr = world.getComponent(entityId, AttributeComp);
if (attr) {
attr.modifiers = attr.modifiers.filter((m) => m.source !== GLOBAL_SLOW_SOURCE);
}
const speedMul = Math.max(0, 1 - slowWan / 10000);
attrs.addModifier(entityId, {
attr: 'move_speed_mul',
op: 'Mul',
value: speedMul,
source: GLOBAL_SLOW_SOURCE,
});
}
/** 对场上全部敌人应用全局减速(选技能后立刻生效) */
export function applyGlobalMonsterSlowToAllEnemies(
session: BattleSession,
skills: readonly ITableSkill[],
): void {
const slowWan = sumSelectedBaseAttrWan(skills, 8);
if (slowWan <= 0) return;
session.world.forEachAlive((id) => {
applyGlobalMonsterSlowToEntity(session, id, slowWan);
});
}
function _isEnemy(world: BattleSession['world'], id: EntityId): boolean {
const team = world.getComponent(id, TeamComp);
if (team && BattleTeamId.isEnemyTeam(team.team)) return true;
const tags = world.getComponent(id, TagComp);
return !!tags?.tags.includes(EntityTag.Enemy);
}
/** Weapon2 是否属于五行英雄(characters 成员) */
export function isHeroWeapon2Id(weapon2Id: number): boolean {
const id = Number(weapon2Id);
if (!Number.isFinite(id) || id <= 0) return false;
const list = gg.data.table.getTableList<ITableHero>(TableNames.Hero) ?? [];
for (const w1 of list) {
if (!isElementHero(w1)) continue;
for (const g of heroCharacterIds(w1)) {
if (Number(g) === id) return true;
}
}
return false;
}
/**
* 背包刷新:按已选全局词条修正 Weapon2 基础权重。
* type10 英雄概率、type11 格子概率:基础 weight ×(1+万分比)。
*/
export function applyBagRefreshWeightBonus(
baseWeight: number,
weapon2Type: number,
weapon2Id: number,
skills: readonly ITableSkill[],
): number {
if (baseWeight <= 0 || !skills.length) return baseWeight;
let wan = 0;
if (Number(weapon2Type) === Weapon2TileType.Grid) {
wan += sumSelectedBaseAttrWan(skills, 11);
}
if (isHeroWeapon2Id(weapon2Id)) {
wan += sumSelectedBaseAttrWan(skills, 10);
}
if (wan <= 0) return baseWeight;
return baseWeight * wanToWeightMul(wan);
}