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/config/BattleHeroTable.ts

158 lines
5.5 KiB

3 weeks ago
import type { EntityId, World } from 'db://assets/mx/module/ecs';
import { GridOccupancyComp, TagComp, UnitMetaComp } from 'db://assets/mx/module/battle/ecs/Components';
import { TableNames } from '../../game/ConfigTableData';
import { PEACH_TREE_WEAPON2_ID } from '../bag/BagPrepConfig';
import { isNonCombatWeapon1 } from '../heros/HeroActorRes';
/** 塔 unitDefId 前缀 */
const TOWER_DEF_PREFIX = 'tower_w1_';
/** 塔 Hero 标签前缀 */
const WEAPON1_TAG_PREFIX = 'weapon1_';
/** 英雄组成文字 id 列表(Hero.text) */
export function heroCharacterIds(hero: ITableHero): readonly number[] {
return hero.text ?? [];
}
/** 指定合成等级对应的普攻技能 id */
export function heroNormalSkillId(hero: ITableHero, composeLevel: number): number {
return _skillIdAtLevel(hero.atk_id, composeLevel);
}
/** 指定合成等级对应的英雄主动技能 id(0=无) */
export function heroUltSkillId(hero: ITableHero | null | undefined, composeLevel = 1): number {
if (!hero) return 0;
return _skillIdAtLevel(hero.act_skill, composeLevel);
}
/** 是否基础单字英雄 */
export function isBasicHero(hero: ITableHero): boolean {
return Number(hero.herotype) === 1;
}
/**
* 单字落下即可攻击来敌(刀/枪/棍/弓)。
* 不含营、铲、桃、组合碎字。
* @param textId Text.id
*/
export function isAttackGlyph(textId: number): boolean {
const id = Number(textId);
if (!(id > 0)) return false;
const heroes = gg.data.table.getTableList<ITableHero>(TableNames.Hero) ?? [];
for (let i = 0; i < heroes.length; i++) {
const hero = heroes[i];
const texts = hero.text ?? [];
if (texts.length !== 1 || Number(texts[0]) !== id) continue;
if (!isBasicHero(hero) || isNonCombatWeapon1(Number(hero.id))) return false;
return heroNormalSkillId(hero, 1) > 0;
}
return false;
}
/** 是否多格组合英雄 */
export function isComboHero(hero: ITableHero): boolean {
return Number(hero.herotype) === 2;
}
/**
* 从塔实体解析 Hero.id(unitDefId / weapon1_ 标签)。
* @param world 战斗世界
* @param entityId 实体
*/
export function resolveTowerHeroId(world: World, entityId: EntityId): number {
const defId = world.getComponent(entityId, UnitMetaComp)?.unitDefId ?? '';
if (defId.startsWith(TOWER_DEF_PREFIX)) {
const id = Number(defId.slice(TOWER_DEF_PREFIX.length));
if (id > 0) return id;
}
const tags = world.getComponent(entityId, TagComp)?.tags;
if (tags) {
for (let i = 0; i < tags.length; i++) {
const t = tags[i];
if (!t.startsWith(WEAPON1_TAG_PREFIX)) continue;
const id = Number(t.slice(WEAPON1_TAG_PREFIX.length));
if (id > 0) return id;
}
}
return 0;
}
/**
* 从塔实体解析 Hero 行。
* @param world 战斗世界
* @param entityId 实体
*/
function resolveTowerHero(world: World, entityId: EntityId): ITableHero | null {
const heroId = resolveTowerHeroId(world, entityId);
if (!(heroId > 0)) return null;
const hero = gg.data.table.getTableData<ITableHero>(TableNames.Hero, heroId);
if (!hero) {
console.log('[BattleHeroTable] Hero 缺失', heroId);
return null;
}
return hero;
}
/**
* 怪物技能 target_stage=1 的默认敌人:敌方阵营、非组合武将(herotype≠2)、非多格组合字。
* @param world 战斗世界
* @param entityId 候选目标
*/
export function isMonsterDefaultEnemyTarget(world: World, entityId: EntityId): boolean {
const hero = resolveTowerHero(world, entityId);
if (hero == null || Number(hero.herotype) === 2) return false;
const cells = world.getComponent(entityId, GridOccupancyComp)?.cells;
return !(cells && cells.length > 1);
}
/**
* 是否蟠桃树塔(Hero/Text id=102,herotype=3)。
* @param world 战斗世界
* @param entityId 候选目标
*/
export function isPeachTreeTower(world: World, entityId: EntityId): boolean {
return resolveTowerHeroId(world, entityId) === PEACH_TREE_WEAPON2_ID;
}
/**
* atk_buff1 类型 12:只锁基础字(herotype=1),不含组合字。
* 损毁态由调用方用 TowerRuinHost 判定,本表不反向依赖战斗宿主。
* @param world 战斗世界
* @param entityId 候选目标
*/
export function isMonsterBasicHeroTarget(world: World, entityId: EntityId): boolean {
if (!isMonsterDefaultEnemyTarget(world, entityId)) return false;
const hero = resolveTowerHero(world, entityId);
return hero != null && isBasicHero(hero);
}
/**
* atk_type=9:Hero.weapon 等于将 id(1刀 2枪 3棍 4弓),含组合武将。
* @param world 战斗世界
* @param entityId 候选目标
* @param weaponType Hero.weapon
*/
export function isHeroWeaponTarget(world: World, entityId: EntityId, weaponType: number): boolean {
if (!(weaponType > 0)) return false;
const hero = resolveTowerHero(world, entityId);
return hero != null && Number(hero.weapon) === weaponType;
}
/** 文字块展示/资源名 */
export function textIconName(text: ITableText): string {
return text.icon ?? '';
}
/** 文字块显示名 */
export function textDisplayName(text: ITableText): string {
const g = text.group?.trim();
return g || textIconName(text);
}
/** 数组按下标取技能 id;composeLevel 从 1 起,越界 clamp */
function _skillIdAtLevel(ids: readonly number[] | null | undefined, composeLevel: number): number {
if (!ids || ids.length <= 0) return 0;
const idx = Math.max(0, Math.min(composeLevel - 1, ids.length - 1));
return ids[idx] ?? 0;
}