|
|
|
|
import { calcMonsterHpBaseByBattleTime } from '../battle/config/MonsterHpCalculator';
|
|
|
|
|
import { TableNames } from '../game/ConfigTableData';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Monster.type(与 AutoTable / Monster.json 对齐)
|
|
|
|
|
* 1 小怪 · 2 BOSS · 3 召唤怪物
|
|
|
|
|
*/
|
|
|
|
|
export enum MonsterType {
|
|
|
|
|
/** 小怪 */
|
|
|
|
|
SmallMonster = 1,
|
|
|
|
|
/** BOSS */
|
|
|
|
|
Boss = 2,
|
|
|
|
|
/** 召唤怪物 */
|
|
|
|
|
SummonMonster = 3,
|
|
|
|
|
/** @deprecated 新表无中期 Boss;数值同 Boss,旧分支兼容 */
|
|
|
|
|
MidBoss = 2,
|
|
|
|
|
/** @deprecated 新表无 */
|
|
|
|
|
SilverBoss = 4,
|
|
|
|
|
/** @deprecated 新表无 */
|
|
|
|
|
GoldenBoss = 5,
|
|
|
|
|
/** @deprecated 新表无 */
|
|
|
|
|
OrangeBoss = 6,
|
|
|
|
|
/** @deprecated 新表无 */
|
|
|
|
|
ZombieFactory = 7,
|
|
|
|
|
/** @deprecated 新表无 */
|
|
|
|
|
TreasureBox = 8,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** icon「小怪金」→ 行进「金小怪」 */
|
|
|
|
|
const ELEMENT_MARCH_BY_ICON: Readonly<Record<string, string>> = {
|
|
|
|
|
小怪金: '金小怪',
|
|
|
|
|
小怪木: '木小怪',
|
|
|
|
|
小怪水: '水小怪',
|
|
|
|
|
小怪火: '火小怪',
|
|
|
|
|
小怪土: '土小怪',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 新 Boss 预制体 icon(仅 default 皮,行进=走路) */
|
|
|
|
|
const NEW_BOSS_ICONS: Readonly<Record<string, boolean>> = {
|
|
|
|
|
Boss金: true,
|
|
|
|
|
Boss木: true,
|
|
|
|
|
Boss水: true,
|
|
|
|
|
Boss火: true,
|
|
|
|
|
Boss土: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 怪物表数据管理 */
|
|
|
|
|
export class MonsterDataManager {
|
|
|
|
|
/** 获取怪物配表列表 */
|
|
|
|
|
public static getAllMonsterList1() {
|
|
|
|
|
return gg.data.table.getTableList<ITableMonster>(TableNames.Monster);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 通过怪物 id 获取配表
|
|
|
|
|
* @param id 怪物 id
|
|
|
|
|
*/
|
|
|
|
|
public static getMonsterDataById(id: number) {
|
|
|
|
|
const allList = this.getAllMonsterList1();
|
|
|
|
|
return allList.find((x) => x.id === id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 是否五行新小怪(不设皮肤、不区分阵营;行进/死亡用系小怪轨)。
|
|
|
|
|
* @param row Monster 行
|
|
|
|
|
*/
|
|
|
|
|
static isElementSmallMonster(row: ITableMonster | null | undefined): boolean {
|
|
|
|
|
if (!row || row.type !== MonsterType.SmallMonster) return false;
|
|
|
|
|
const icon = String(row.icon ?? '').trim();
|
|
|
|
|
return !!ELEMENT_MARCH_BY_ICON[icon];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 是否新 Boss(不设皮肤、不区分阵营;行进=走路)。
|
|
|
|
|
* @param row Monster 行
|
|
|
|
|
*/
|
|
|
|
|
static isNewElementBoss(row: ITableMonster | null | undefined): boolean {
|
|
|
|
|
if (!row || !this.isBossType(row.type)) return false;
|
|
|
|
|
const icon = String(row.icon ?? '').trim();
|
|
|
|
|
return !!NEW_BOSS_ICONS[icon];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 新怪表现:不 setSkin。
|
|
|
|
|
* @param row Monster 行
|
|
|
|
|
*/
|
|
|
|
|
static skipsBattleSpineSkin(row: ITableMonster | null | undefined): boolean {
|
|
|
|
|
return this.isElementSmallMonster(row) || this.isNewElementBoss(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 行进动画名。五行小怪=`{系}小怪`;新 Boss=`走路`;其它=`走路`。
|
|
|
|
|
* @param row Monster 行
|
|
|
|
|
*/
|
|
|
|
|
static resolveMarchAnim(row: ITableMonster | null | undefined): string {
|
|
|
|
|
if (!row) {
|
|
|
|
|
console.error('[MonsterDataManager] resolveMarchAnim 无配表');
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
if (this.isElementSmallMonster(row)) {
|
|
|
|
|
const icon = String(row.icon ?? '').trim();
|
|
|
|
|
const anim = ELEMENT_MARCH_BY_ICON[icon];
|
|
|
|
|
if (!anim) {
|
|
|
|
|
console.error('[MonsterDataManager] 五行小怪 icon 无法映射行进动画', row.id, icon);
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
return anim;
|
|
|
|
|
}
|
|
|
|
|
return '走路';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 死亡动画名。五行小怪=`{系}小怪2`;无契约轨返回空(走外部死亡特效)。
|
|
|
|
|
* @param row Monster 行
|
|
|
|
|
*/
|
|
|
|
|
static resolveDeathAnim(row: ITableMonster | null | undefined): string {
|
|
|
|
|
if (!row) {
|
|
|
|
|
console.error('[MonsterDataManager] resolveDeathAnim 无配表');
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
if (!this.isElementSmallMonster(row)) return '';
|
|
|
|
|
const march = this.resolveMarchAnim(row);
|
|
|
|
|
if (!march) return '';
|
|
|
|
|
return `${march}2`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @deprecated 新五行怪不设皮肤;仅旧多皮资源(猴/哮天犬等)仍用。
|
|
|
|
|
* - type1 小怪 / type3 召唤:己方口=`icon`,敌方口=`icon`+`2`
|
|
|
|
|
* - type2 Boss:己方口=`皮肤字1_1`,敌方口=`皮肤字2_1`
|
|
|
|
|
* @param row Monster 行
|
|
|
|
|
* @param enemyCamp 是否敌方出怪口放出的怪
|
|
|
|
|
*/
|
|
|
|
|
public static resolveBattleSpineSkin(row: ITableMonster, enemyCamp: boolean): string {
|
|
|
|
|
if (this.skipsBattleSpineSkin(row)) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
const icon = String(row.icon ?? '').trim();
|
|
|
|
|
if (row.type === MonsterType.SmallMonster || row.type === MonsterType.SummonMonster) {
|
|
|
|
|
if (!icon) {
|
|
|
|
|
console.error('[MonsterDataManager] 怪物 icon 为空,无法定皮肤', row.id, row.type);
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
return enemyCamp ? `${icon}2` : icon;
|
|
|
|
|
}
|
|
|
|
|
if (row.type === MonsterType.Boss) {
|
|
|
|
|
return enemyCamp ? '皮肤字2_1' : '皮肤字1_1';
|
|
|
|
|
}
|
|
|
|
|
if (!icon) {
|
|
|
|
|
console.error('[MonsterDataManager] 怪物 icon 为空', row.id, row.type);
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 可被吞噬的小兵:小怪或召唤物,不含 Boss。
|
|
|
|
|
* @param monsterId Monster.id
|
|
|
|
|
*/
|
|
|
|
|
static isDevourMinion(monsterId: number): boolean {
|
|
|
|
|
const row = this.getMonsterDataById(monsterId);
|
|
|
|
|
if (!row) return false;
|
|
|
|
|
return row.type === MonsterType.SmallMonster || row.type === MonsterType.SummonMonster;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 是否为 Boss 类型(含旧表银/金/橙 Boss)。
|
|
|
|
|
* @param type Monster.type
|
|
|
|
|
*/
|
|
|
|
|
static isBossType(type: number): boolean {
|
|
|
|
|
return type === MonsterType.Boss
|
|
|
|
|
|| type === MonsterType.SilverBoss
|
|
|
|
|
|| type === MonsterType.GoldenBoss
|
|
|
|
|
|| type === MonsterType.OrangeBoss;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 通过难度和时间和战力获取怪物血量
|
|
|
|
|
* @param diff 难度
|
|
|
|
|
* @param time 时间
|
|
|
|
|
* @param power 战力
|
|
|
|
|
* @param powerPara 战力参数(玩家战力 >= 推荐)
|
|
|
|
|
* @param powerPara2 战力参数(玩家战力 < 推荐)
|
|
|
|
|
*/
|
|
|
|
|
public static getMonsterHpByDiffAndTime(
|
|
|
|
|
diff: number,
|
|
|
|
|
time: number,
|
|
|
|
|
power: number,
|
|
|
|
|
powerPara: number,
|
|
|
|
|
powerPara2: number = 0,
|
|
|
|
|
) {
|
|
|
|
|
return calcMonsterHpBaseByBattleTime(diff, time, power, powerPara, powerPara2);
|
|
|
|
|
}
|
|
|
|
|
}
|