Files
pixelheros/assets/script/game/common/config/TalentSet.ts
panFD 8ce83dc5e2 chore: 停用风怒机制并移除相关所有代码
全面移除游戏中风怒相关的所有内容,包括属性、技能、天赋、成就、UI展示、配置数据和结算逻辑,清理所有残留的风怒机制代码和配置项。
2026-08-24 23:48:40 +08:00

273 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Attrs } from "./HeroAttrs";
import { HRole } from "./heroSet";
/**
* 天赋系统配置(局外成长:升级即激活,战斗中对英雄属性常驻加成)。
*
* 双层结构:
* - 基础天赋:全局生效,对所有英雄叠加;
* - 专精天赋:按 HRole 职业过滤,仅对匹配职业的英雄生效,且要求前置天赋达到指定等级。
*
* 结算口径(与项目 buff 规范一致):
* - percent 模式:按英雄基础值(base_ap/base_hp/hero.def)相对放大;
* - flat 模式:概率/抗性类按百分点累加,defense 按固定点数累加。
*/
/** 天赋数值模式:percent=按基础值百分比放大;flat=固定值/百分点累加 */
export enum TalentValueMode {
Percent = 0,
Flat = 1,
}
/** 单条属性加成词条 */
export interface TalentAttrBonus {
/** 目标属性(Attrs 枚举键) */
attr: Attrs;
/** 数值模式 */
mode: TalentValueMode;
/** 每级数值(percent 模式为百分比;flat 模式为百分点/固定值) */
per_lv: number;
}
/** 天赋配置 */
export interface TalentConfig {
/** 天赋 uuid(段位见 TalentSet 注释) */
uuid: number;
/** 天赋名称 */
name: string;
/** 描述(UI 展示) */
info: string;
/** 属性加成词条列表(每级叠加) */
bonuses: TalentAttrBonus[];
/** 最大等级 */
max_lv: number;
/** 专精天赋:仅对该职业英雄生效;基础天赋省略此字段 */
role?: HRole;
/** 专精天赋:前置要求(前置天赋 uuid + 所需等级),全部满足才生效 */
requires?: { uuid: number; lv: number }[];
}
/** 单条已解析的加成(等级已乘算) */
export interface TalentResolvedBonus {
attr: Attrs;
mode: TalentValueMode;
/** 总值 = per_lv × 天赋等级 */
value: number;
}
/**
* 天赋加成作用目标的最小结构接口(TS 结构化类型,HeroAttrsComp 天然满足)。
* Why: 用结构化接口替代直接 import HeroAttrsComp,避免 config → hero → SingletonModuleComp → config 的循环依赖。
*/
export interface ITalentTarget {
ap: number;
hp: number;
hp_max: number;
defense: number;
/** 基础攻击快照(percent 模式的基数) */
base_ap: number;
/** 基础血量快照(percent 模式的基数) */
base_hp: number;
/** 防御基础值(percent 模式的基数,等于 hero.def) */
[key: string]: any;
}
/**
* 天赋配置表。
* uuid 段位:9001-9099 基础天赋(全局);9101-9199 专精天赋(按职业过滤)。
*/
export const TalentSet: Record<number, TalentConfig> = {
// ==================== 基础天赋(9001-9099,全局生效) ====================
9001: {
uuid: 9001, name: "攻击强化", info: "所有英雄攻击 +{value}%",
bonuses: [{ attr: Attrs.ap, mode: TalentValueMode.Percent, per_lv: 3 }],
max_lv: 5,
},
9002: {
uuid: 9002, name: "生命强化", info: "所有英雄生命 +{value}%",
bonuses: [{ attr: Attrs.hp_max, mode: TalentValueMode.Percent, per_lv: 5 }],
max_lv: 5,
},
9003: {
uuid: 9003, name: "防御强化", info: "所有英雄防御 +{value} 点",
bonuses: [{ attr: Attrs.defense, mode: TalentValueMode.Flat, per_lv: 8 }],
max_lv: 5,
},
9004: {
uuid: 9004, name: "暴击强化", info: "所有英雄暴击率 +{value}%",
bonuses: [{ attr: Attrs.critical, mode: TalentValueMode.Flat, per_lv: 2 }],
max_lv: 5,
},
9005: {
uuid: 9005, name: "击晕强化", info: "所有英雄击晕率 +{value}%",
bonuses: [{ attr: Attrs.stun_chance, mode: TalentValueMode.Flat, per_lv: 2 }],
max_lv: 5,
},
9006: {
uuid: 9006, name: "冰冻强化", info: "所有英雄冰冻率 +{value}%",
bonuses: [{ attr: Attrs.freeze_chance, mode: TalentValueMode.Flat, per_lv: 2 }],
max_lv: 5,
},
9007: {
uuid: 9007, name: "击退强化", info: "所有英雄击退距离 +{value}",
bonuses: [{ attr: Attrs.knockback_distance, mode: TalentValueMode.Flat, per_lv: 10 }],
max_lv: 5,
},
// 风怒机制已停用: 9008 风怒强化天赋已移除
/*
9008: {
uuid: 9008, name: "风怒强化", info: "所有英雄风怒率 +{value}%",
bonuses: [{ attr: Attrs.wfuny, mode: TalentValueMode.Flat, per_lv: 2 }],
max_lv: 5,
},
*/
// ==================== 专精天赋(9101-9199,按职业过滤 + 前置要求) ====================
// 坦克专精:前置 防御强化 Lv3 → 坦克大量防御 + 生命
9101: {
uuid: 9101, name: "坦克专精", info: "坦克防御 +{value}%、生命 +{value2}%",
bonuses: [
{ attr: Attrs.defense, mode: TalentValueMode.Percent, per_lv: 30 },
{ attr: Attrs.hp_max, mode: TalentValueMode.Percent, per_lv: 5 },
],
max_lv: 5, role: HRole.Tank,
requires: [{ uuid: 9003, lv: 3 }],
},
// 战士专精:前置 生命强化 Lv3 → 战士大量生命
9102: {
uuid: 9102, name: "战士专精", info: "战士生命 +{value}%",
bonuses: [{ attr: Attrs.hp_max, mode: TalentValueMode.Percent, per_lv: 12 }],
max_lv: 5, role: HRole.Warrior,
requires: [{ uuid: 9002, lv: 3 }],
},
// 刺客专精:前置 暴击强化 Lv3 → 刺客攻击 + 暴击
9103: {
uuid: 9103, name: "刺客专精", info: "刺客攻击 +{value}%、暴击率 +{value2}%",
bonuses: [
{ attr: Attrs.ap, mode: TalentValueMode.Percent, per_lv: 8 },
{ attr: Attrs.critical, mode: TalentValueMode.Flat, per_lv: 2 },
],
max_lv: 5, role: HRole.Assassin,
requires: [{ uuid: 9004, lv: 3 }],
},
// 射手专精:前置 攻击强化 Lv3 → 射手攻击 + 穿透
9104: {
uuid: 9104, name: "射手专精", info: "射手攻击 +{value}%、穿透率 +{value2}%",
bonuses: [
{ attr: Attrs.ap, mode: TalentValueMode.Percent, per_lv: 8 },
{ attr: Attrs.puncture_chance, mode: TalentValueMode.Flat, per_lv: 2 },
],
max_lv: 5, role: HRole.Archer,
requires: [{ uuid: 9001, lv: 3 }],
},
// 法师专精:前置 冰冻强化 Lv3 → 法师攻击 + 冰冻率
9105: {
uuid: 9105, name: "法师专精", info: "法师攻击 +{value}%、冰冻率 +{value2}%",
bonuses: [
{ attr: Attrs.ap, mode: TalentValueMode.Percent, per_lv: 8 },
{ attr: Attrs.freeze_chance, mode: TalentValueMode.Flat, per_lv: 2 },
],
max_lv: 5, role: HRole.Mage,
requires: [{ uuid: 9006, lv: 3 }],
},
// 辅助专精:前置 生命强化 Lv3 → 治疗量提升 + 施加的友方 buff 效果放大
9106: {
uuid: 9106, name: "辅助专精", info: "辅助治疗量 +{value}%、施加的增益效果 +{value2}%",
bonuses: [
{ attr: Attrs.heal_power, mode: TalentValueMode.Flat, per_lv: 10 },
{ attr: Attrs.buff_power, mode: TalentValueMode.Flat, per_lv: 8 },
],
max_lv: 5, role: HRole.Support,
requires: [{ uuid: 9002, lv: 3 }],
},
};
/** 天赋升级消耗:索引为当前等级(0 表示升到 1 级),返回所需天赋点数 */
export const TALENT_UPGRADE_COST: number[] = [1, 1, 2, 2, 3];
/**
* 查询升级所需天赋点数
* @param curLv 当前等级
* @returns 升到下一级所需点数;已满级返回 -1
*/
export function getTalentUpgradeCost(curLv: number): number {
if (curLv < 0 || curLv >= TALENT_UPGRADE_COST.length) return -1;
return TALENT_UPGRADE_COST[curLv];
}
/**
* 聚合指定职业英雄生效的全部天赋加成。
* Why: 基础天赋全局生效,专精天赋按 role 过滤且要求前置天赋达标;
* 战斗加载时(Hero.load / applyHeroLevel)调用本函数一次性取出本英雄的天赋加成区。
* @param levels 天赋等级表(key 为天赋 uuid,value 为当前等级)
* @param role 英雄职业(专精过滤依据;无 role 时只应用基础天赋)
* @returns 已解析的加成列表(等级已乘算进 value)
*/
export function getTalentBonusesForRole(levels: Record<number, number>, role?: HRole): TalentResolvedBonus[] {
const result: TalentResolvedBonus[] = [];
if (!levels) return result;
for (const key in levels) {
const lv = levels[key];
if (lv <= 0) continue;
const cfg = TalentSet[key];
if (!cfg) continue;
// 专精天赋:职业不匹配则跳过
if (cfg.role !== undefined && cfg.role !== role) continue;
// 前置要求:任一前置天赋等级不足则不生效
if (cfg.requires) {
let ok = true;
for (const req of cfg.requires) {
if ((levels[req.uuid] ?? 0) < req.lv) { ok = false; break; }
}
if (!ok) continue;
}
for (const b of cfg.bonuses) {
result.push({ attr: b.attr, mode: b.mode, value: b.per_lv * lv });
}
}
return result;
}
/**
* 将天赋加成写入英雄属性模型(在 Hero.load / MissionCardComp.applyHeroLevel 的属性组装段调用)。
*
* 结算规则:
* - Percent 模式:以基础快照为基数(ap→base_ap,hp_max→base_hp,defense→def_base),按百分比放大后累加;
* - Flat 模式:直接按属性名动态累加(概率/抗性类为百分点,defense 为固定点数)。
*
* Why: percent 必须用基础快照而非当前 ap/hp_max 作基数——当前值已含驻场光环与成长增量,
* 若以当前值为基数会与光环乘区叠加成乘法,导致数值膨胀失控。
*
* @param model 英雄属性模型(满足 ITalentTarget 结构)
* @param levels 天赋等级表(smc.getTalentLevels())
* @param role 英雄职业(专精过滤;无 role 的怪物由调用方跳过)
*/
export function applyTalentBonuses(model: ITalentTarget, levels: Record<number, number>, role?: HRole): void {
const bonuses = getTalentBonusesForRole(levels, role);
if (bonuses.length === 0) return;
// percent 模式的 defense 基数:取调用方传入的当前 defense(Hero.load/applyHeroLevel 已在调用前重置为 hero.def)
const defBase = model.defense;
for (const b of bonuses) {
if (b.mode === TalentValueMode.Percent) {
switch (b.attr) {
case Attrs.ap:
model.ap += Math.floor(model.base_ap * b.value / 100);
break;
case Attrs.hp_max:
model.hp_max += Math.floor(model.base_hp * b.value / 100);
model.hp += Math.floor(model.base_hp * b.value / 100);
break;
case Attrs.defense:
model.defense += Math.floor(defBase * b.value / 100);
break;
default:
model[b.attr] = (typeof model[b.attr] === "number" ? model[b.attr] : 0) + b.value;
break;
}
} else {
// flat:概率/抗性类百分点累加,defense 固定点数累加
model[b.attr] = (typeof model[b.attr] === "number" ? model[b.attr] : 0) + b.value;
}
}
}