refactor(hero): 重构英雄数值系统,支持品质系数与12级职业属性加成

1. 调整英雄最大等级为99,实现近似无限升级
2. 新增防御属性加成系统,补充def_bonus相关配置与计算
3. 引入英雄品质系数机制,相邻品质基础属性相差5%
4. 新增12级职业属性专项加成:坦克加防、战士辅助加血、输出加攻
5. 更新英雄设计文档与配置示例,统一数值计算逻辑
6. 重构成长计算函数,支持防御属性成长与加成
This commit is contained in:
panFD
2026-09-01 20:47:36 +08:00
parent d943bc05ce
commit 1dbb3bd90d
6 changed files with 185 additions and 68 deletions

View File

@@ -40,8 +40,8 @@ export enum FightSet {
HEARTPOS = -320,//基地位置
/** 场上英雄编制数:由开局 3 次三选一固定,玩家无法扩充 */
HERO_FIELD_NUM = 3,
/** 英雄可升级到的最高等级(通过升级卡提升) */
HERO_MAX_LV = 6,
/** 英雄可升级到的最高等级(通过升级卡提升),99 近似无限升级 */
HERO_MAX_LV = 99,
/** 英雄技能等级上限(无限升级下技能 5 级封顶,超出等级只长属性) */
HERO_SKILL_MAX_LV = 5,
/** 英雄属性随等级成长的倍率(ap/hp = base * MULTIPLIER^(lv-1)) */

View File

@@ -1,4 +1,4 @@
import { v3 } from "cc"
import { v3 } from "cc"
import { BoxSet, FacSet, FightSet } from "./GameSet"
import { SkillOverrides, TGroup, SkillSet, FieldSkillSet, SkillConfig, SkillKind, FieldSkillConfig, FieldSkillType, mergeSkillParams } from "./SkillSet"
import { BuffList, BuffConfig, ModOp } from "./BuffSet"
@@ -107,15 +107,37 @@ export enum HGrowType {
}
/** 成长类型系数表(每级增量 = 英雄基础属性 × 对应系数) */
export const HERO_GROW_COEF: Record<HGrowType, { hp: number; ap: number }> = {
[HGrowType.Tank]: { hp: 1.5, ap: 0.6 },
[HGrowType.Warrior]: { hp: 1.0, ap: 1.0 },
[HGrowType.Assassin]: { hp: 0.7, ap: 1.4 },
[HGrowType.Mage]: { hp: 0.9, ap: 1.3 },
[HGrowType.Support]: { hp: 1.1, ap: 0.7 },
[HGrowType.Archer]: { hp: 0.8, ap: 1.3 },
export const HERO_GROW_COEF: Record<HGrowType, { hp: number; ap: number; def: number }> = {
[HGrowType.Tank]: { hp: 1.5, ap: 0.6, def: 1.5 },
[HGrowType.Warrior]: { hp: 1.0, ap: 1.0, def: 1.0 },
[HGrowType.Assassin]: { hp: 0.7, ap: 1.4, def: 0.5 },
[HGrowType.Mage]: { hp: 0.9, ap: 1.3, def: 0.5 },
[HGrowType.Support]: { hp: 1.1, ap: 0.7, def: 1.0 },
[HGrowType.Archer]: { hp: 0.8, ap: 1.3, def: 0.5 },
};
/**
* 英雄品质系数步长:相邻品质(card_lv)基础属性相差 5%。
* 系数 = 1 + HERO_QUALITY_STEP × (card_lv - 1),lv1~lv5 → 1.00/1.05/1.10/1.15/1.20。
* 仅作用于 lv1 初始基础属性(AP/HP/DEF),成长与等级 bonus 不随品质缩放。
*/
export const HERO_QUALITY_STEP = 0.05;
/** 计算英雄品质系数(相邻品质基础属性差 5%) */
export function getHeroQualityCoef(cardLv: number): number {
return 1 + HERO_QUALITY_STEP * (Math.max(1, cardLv) - 1);
}
/**
* lv12 职业属性专项:英雄等级达到 12 级时,按职业对单项基础属性 +50%。
* 基数为 lv11 当前等级有效值(基础 + 成长 + lv9 bonus,不含 lv12 自身)。
* Why: 坦克堆防、战士/辅助堆血、输出位堆攻,强化职业特色。
*/
export const HERO_LV12_SPECIAL_LV = 12;
/** lv12 专项提升的档位等级(基数取 LV12 - 1 = 11 级有效值) */
export const HERO_LV12_BASE_LV = HERO_LV12_SPECIAL_LV - 1;
/**
* 英雄位置类型(职业定位)。
* Why: grow_type 仅驱动数值成长曲线,无法表达"这个英雄在阵容里干什么";
@@ -139,6 +161,16 @@ export const HRoleName: Record<HRole, string> = {
[HRole.Support]: "辅助",
};
/** lv12 各职业专项属性映射(坦克堆防、战士/辅助堆血、输出位堆攻) */
export const HERO_LV12_SPECIAL_ATTR: Record<HRole, "def" | "hp" | "ap"> = {
[HRole.Tank]: "def",
[HRole.Warrior]: "hp",
[HRole.Assassin]: "ap",
[HRole.Archer]: "ap",
[HRole.Mage]: "ap",
[HRole.Support]: "hp",
};
/**
* 职业基础属性模板(仅英雄使用,怪物无 role 直接手写 hp/ap/def)。
* 英雄配置处的 hp/ap/def = 本模板值 + 该卡手动增量,模板保证同职业基准一致、增量表达个体差异。
@@ -158,16 +190,17 @@ export const HERO_ROLE_BASE: Record<HRole, { hp: number; ap: number; def: number
* 公式:累计 = 基础属性 × 类型系数 × (lv - 1)。
* Why: 以英雄自身基础值为基数,自动适配低/高费卡的成长占比,避免全局固定值失衡;
* 线性曲线在无限升级下不会指数爆炸,强度平滑可控。
* @param hero 英雄配置(取 hp/ap 基础值与 grow_type)
* @param hero 英雄配置(取 hp/ap/def 基础值与 grow_type)
* @param targetLv 目标等级(≥1)
* @returns 累计 hp/ap 增量(已取整)
* @returns 累计 hp/ap/def 增量(已取整)
*/
export function calcGrowBonus(hero: Pick<heroInfo, "hp" | "ap" | "grow_type">, targetLv: number): { hp: number; ap: number } {
export function calcGrowBonus(hero: Pick<heroInfo, "hp" | "ap" | "def" | "grow_type">, targetLv: number): { hp: number; ap: number; def: number } {
const coef = HERO_GROW_COEF[hero.grow_type ?? HGrowType.Warrior];
const steps = Math.max(0, Math.floor(targetLv) - 1);
return {
hp: Math.floor(hero.hp * coef.hp * steps),
ap: Math.floor(hero.ap * coef.ap * steps),
def: Math.floor(hero.def * coef.def * steps),
};
}
@@ -295,6 +328,7 @@ export interface heroInfo {
skills: Record<number, HSkillInfo>; // 携带技能ID列表
ap_bonus?: LvBonusEntry[]; // 额外攻击加成(按 lv 升序,运行时累加 ≤英雄等级 的所有档)
hp_bonus?: LvBonusEntry[]; // 额外生命加成(按 lv 升序,运行时累加 ≤英雄等级 的所有档)
def_bonus?: LvBonusEntry[]; // 额外防御加成(按 lv 升序,运行时累加 ≤英雄等级 的所有档)
info: string; // 描述文案
/**
* @deprecated 已废弃:无任何 UI/运行时读取。技能提升说明由 HeroSkillText 依据
@@ -422,8 +456,10 @@ export interface LvBonusEntry {
*=============英雄配置列表================
* 几何王国复刻版 — 依据 英雄设计指引.md(A/B 级复刻英雄)配置
*
* 规则:lv3 解锁 atking/atked 触发技能,lv2 解锁 fstart,lv6/12 大招走 lv_entries 分档成长,
* lv9 card_lv 4/5 配 field 光环,card_lv 3 配 ap_bonus/hp_bonus 基础属性+50%
* 规则:lv1 激活 skills[0]/skills[1],lv6 解锁 atking/atked/fstart 触发技能,
* 大招(skills[1])lv9/lv16 走 lv_entries 分档成长,lv12 按职业对单项基础属性 +50%(基数取 lv11 有效值),
* lv9 card_lv 4/5 配 field 光环,card_lv 3 配 ap_bonus/hp_bonus 基础属性+50%,
* 品质(card_lv)相邻基础属性差 5%(仅 lv1 初始 AP/HP/DEF)
* 编号:本批复刻英雄集中于 5001~5009,card_lv 按配置(不遵循段位规则)
*/
@@ -443,14 +479,14 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { ap: 250, bck: 30, para: 40, summon_count: 1 },
desc: "释放能量波,对{target}造成攻击力{ap}%伤害,击退{bck},{para}%概率麻痹",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { ap: 250, bck: 60, para: 40, summon_count: 1 } },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { ap: 300, bck: 90, timed_buff_id: 7005, para: 50, summon_count: 2 }, desc: "释放能量波,对{target}造成攻击力{ap}%伤害,击退{bck},{para}%概率麻痹,额外释放1次,并使目标中毒(每0.5秒受到{buff_value}点毒伤,持续{dur}秒)" },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { ap: 250, bck: 60, para: 40, summon_count: 1 } },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { ap: 300, bck: 90, timed_buff_id: 7005, para: 50, summon_count: 2 }, desc: "释放能量波,对{target}造成攻击力{ap}%伤害,击退{bck},{para}%概率麻痹,额外释放1次,并使目标中毒(每0.5秒受到{buff_value}点毒伤,持续{dur}秒)" },
],
},
},
atking: {
6010: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "雷霆万钧", t_num: 3, overrides: { para: 100 }, desc: "释放紫魔球轰击{target},{para}%概率麻痹目标" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "雷霆万钧", t_num: 3, overrides: { para: 100 }, desc: "释放紫魔球轰击{target},{para}%概率麻痹目标" },
],
},
field: [
@@ -469,14 +505,14 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { ap: 150 },
desc: "斩出光闪,对{target}造成攻击力{ap}%伤害",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { ap: 150, timed_buff_id: 7007 }, desc: "斩出光闪,对{target}造成攻击力{ap}%伤害,并使目标出血(每0.5秒受到{buff_value}点伤害,持续{dur}秒)" },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { ap: 180, hit_count: 8, num: 1 }, desc: "斩出光闪,对{target}连击{hit_count}次,每次造成攻击力{ap}%伤害,并双发{num}次" },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { ap: 150, timed_buff_id: 7007 }, desc: "斩出光闪,对{target}造成攻击力{ap}%伤害,并使目标出血(每0.5秒受到{buff_value}点伤害,持续{dur}秒)" },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { ap: 180, hit_count: 8, num: 1 }, desc: "斩出光闪,对{target}连击{hit_count}次,每次造成攻击力{ap}%伤害,并双发{num}次" },
],
},
},
atking: {
6004: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "致命节奏", t_num: 3, overrides: { crt: 30 }, desc: "释放斩击,{crt}%概率造成暴击" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "致命节奏", t_num: 3, overrides: { crt: 30 }, desc: "释放斩击,{crt}%概率造成暴击" },
],
},
field: [
@@ -495,19 +531,19 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { ap: 150, para: 40, summon_count: 1 },
desc: "召唤落雷斩击{target},造成攻击力{ap}%伤害,{para}%概率麻痹",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { ap: 150, timed_buff_id: 7006, para: 40, summon_count: 1 }, desc: "召唤落雷斩击{target},造成攻击力{ap}%伤害,{para}%概率麻痹,并使目标攻击力{buff_value}%(持续{dur}秒)" },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { ap: 180, timed_buff_id: 7006, buff_value: -15, para: 50, summon_count: 2 } },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { ap: 150, timed_buff_id: 7006, para: 40, summon_count: 1 }, desc: "召唤落雷斩击{target},造成攻击力{ap}%伤害,{para}%概率麻痹,并使目标攻击力{buff_value}%(持续{dur}秒)" },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { ap: 180, timed_buff_id: 7006, buff_value: -15, para: 50, summon_count: 2 } },
],
},
},
atked: {
6301: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "罗生门", t_num: 4, overrides: { TGroup: TGroup.Self, ap: 2 }, desc: "{target}获得{ap}次格挡护盾" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "罗生门", t_num: 4, overrides: { TGroup: TGroup.Self, ap: 2 }, desc: "{target}获得{ap}次格挡护盾" },
],
},
fstart: {
6200: [
{ lv: 2, s_lv: SkillLv.Lv1, name: "三十六烦恼凤", t_num: 1, overrides: { ap: 500 }, desc: "入场释放剑气,对{target}造成攻击力{ap}%伤害" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "三十六烦恼凤", t_num: 1, overrides: { ap: 500 }, desc: "入场释放剑气,对{target}造成攻击力{ap}%伤害" },
],
},
field: [
@@ -526,14 +562,14 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { ap: 150, summon_count: 1 },
desc: "释放能量波,对{target}造成攻击力{ap}%伤害",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { ap: 150, frz: 15, summon_count: 1 }, desc: "释放能量波,对{target}造成攻击力{ap}%伤害,{frz}%概率冰冻" },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { ap: 180, frz: 30, hit_count: 8, summon_count: 2 }, desc: "释放能量波,对{target}造成攻击力{ap}%伤害,{frz}%概率冰冻,命中{hit_count}次" },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { ap: 150, frz: 15, summon_count: 1 }, desc: "释放能量波,对{target}造成攻击力{ap}%伤害,{frz}%概率冰冻" },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { ap: 180, frz: 30, hit_count: 8, summon_count: 2 }, desc: "释放能量波,对{target}造成攻击力{ap}%伤害,{frz}%概率冰冻,命中{hit_count}次" },
],
},
},
atking: {
6009: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "霜寒之触", t_num: 3, overrides: { timed_buff_id: 7003 }, desc: "释放寒气,冰冻{target}{dur}秒" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "霜寒之触", t_num: 3, overrides: { timed_buff_id: 7003 }, desc: "释放寒气,冰冻{target}{dur}秒" },
],
},
field: [
@@ -552,19 +588,19 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { TGroup: TGroup.Self, ap: 3, summon_count: 1 },
desc: "{target}获得{ap}次格挡护盾",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { TGroup: TGroup.Self, ap: 5, summon_count: 1 } },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { TGroup: TGroup.Self, ap: 6, summon_count: 2 } },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { TGroup: TGroup.Self, ap: 5, summon_count: 1 } },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { TGroup: TGroup.Self, ap: 6, summon_count: 2 } },
],
},
},
atked: {
6004: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "反击减攻", t_num: 4, overrides: { timed_buff_id: 7006 }, desc: "反击使攻击者攻击力{buff_value}%,持续{dur}秒" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "反击减攻", t_num: 4, overrides: { timed_buff_id: 7006 }, desc: "反击使攻击者攻击力{buff_value}%,持续{dur}秒" },
],
},
fstart: {
6412: [
{ lv: 2, s_lv: SkillLv.Lv1, name: "铁壁壁垒", t_num: 1, overrides: { TGroup: TGroup.Team, ap: 50 }, desc: "{target}防御提升{ap}点" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "铁壁壁垒", t_num: 1, overrides: { TGroup: TGroup.Team, ap: 50 }, desc: "{target}防御提升{ap}点" },
],
},
dead: {
@@ -592,19 +628,19 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { TGroup: TGroup.Team, ap: 300, summon_count: 1 },
desc: "为{target}回复攻击力{ap}%生命",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { TGroup: TGroup.Team, ap: 400, summon_count: 1 } },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { TGroup: TGroup.Team, ap: 450, summon_count: 2 } },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { TGroup: TGroup.Team, ap: 400, summon_count: 1 } },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { TGroup: TGroup.Team, ap: 450, summon_count: 2 } },
],
},
},
atking: {
6302: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "圣洁之锤", t_num: 3, overrides: { TGroup: TGroup.Self, ap: 100 }, desc: "释放圣光,为{target}回复攻击力{ap}%生命" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "圣洁之锤", t_num: 3, overrides: { TGroup: TGroup.Self, ap: 100 }, desc: "释放圣光,为{target}回复攻击力{ap}%生命" },
],
},
fstart: {
6412: [
{ lv: 2, s_lv: SkillLv.Lv1, name: "圣光庇佑", t_num: 1, overrides: { TGroup: TGroup.Team, ap: 30 }, desc: "{target}防御提升{ap}点" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "圣光庇佑", t_num: 1, overrides: { TGroup: TGroup.Team, ap: 30 }, desc: "{target}防御提升{ap}点" },
],
},
field: [
@@ -623,14 +659,14 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { ap: 150, summon_count: 1 },
desc: "斩出气刃,对{target}造成攻击力{ap}%伤害",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { ap: 150, timed_buff_id: 7002, summon_count: 1 }, desc: "斩出气刃,对{target}造成攻击力{ap}%伤害,并使目标易伤(受到伤害加深,持续{dur}秒)" },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { ap: 180, bck: 60, timed_buff_id: 7002, buff_value: 20, summon_count: 2 }, desc: "斩出气刃,对{target}造成攻击力{ap}%伤害,击退{bck},并使目标易伤(持续{dur}秒)" },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { ap: 150, timed_buff_id: 7002, summon_count: 1 }, desc: "斩出气刃,对{target}造成攻击力{ap}%伤害,并使目标易伤(受到伤害加深,持续{dur}秒)" },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { ap: 180, bck: 60, timed_buff_id: 7002, buff_value: 20, summon_count: 2 }, desc: "斩出气刃,对{target}造成攻击力{ap}%伤害,击退{bck},并使目标易伤(持续{dur}秒)" },
],
},
},
atking: {
6004: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "雷霆一击", t_num: 3, overrides: { bck: 40 }, desc: "重击{target},击退{bck}" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "雷霆一击", t_num: 3, overrides: { bck: 40 }, desc: "重击{target},击退{bck}" },
],
},
// card_lv 3:lv9 无光环,改为基础属性+50%
@@ -649,14 +685,14 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { ap: 300, summon_count: 1 },
desc: "劈出开山斧,对{target}造成攻击力{ap}%伤害",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { ap: 300, stun: 20, summon_count: 1 }, desc: "劈出开山斧,对{target}造成攻击力{ap}%伤害,{stun}%概率击晕" },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { ap: 350, stun: 35, hit_count: 8, summon_count: 2 }, desc: "劈出开山斧,对{target}造成攻击力{ap}%伤害,{stun}%概率击晕,命中{hit_count}次" },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { ap: 300, stun: 20, summon_count: 1 }, desc: "劈出开山斧,对{target}造成攻击力{ap}%伤害,{stun}%概率击晕" },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { ap: 350, stun: 35, hit_count: 8, summon_count: 2 }, desc: "劈出开山斧,对{target}造成攻击力{ap}%伤害,{stun}%概率击晕,命中{hit_count}次" },
],
},
},
atking: {
6004: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "火眼金睛", t_num: 3, overrides: { crt: 25 }, desc: "释放斩击,{crt}%概率造成暴击" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "火眼金睛", t_num: 3, overrides: { crt: 25 }, desc: "释放斩击,{crt}%概率造成暴击" },
],
},
field: [
@@ -675,20 +711,20 @@ export const HeroInfo: Record<number, heroInfo> = {
overrides: { ap: 150, summon_count: 1 },
desc: "斩出气刃,对{target}造成攻击力{ap}%伤害",
lv_entries: [
{ lv: 6, s_lv: SkillLv.Lv2, overrides: { ap: 180, summon_count: 1 } },
{ lv: 12, s_lv: SkillLv.Lv3, overrides: { ap: 200, summon_count: 2 } },
{ lv: 9, s_lv: SkillLv.Lv2, overrides: { ap: 180, summon_count: 1 } },
{ lv: 16, s_lv: SkillLv.Lv3, overrides: { ap: 200, summon_count: 2 } },
],
},
},
atking: {
6302: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "嗜血战斧", t_num: 4, overrides: { TGroup: TGroup.Self, ap: 120 }, desc: "释放嗜血斩击,为{target}回复攻击力{ap}%生命" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "嗜血战斧", t_num: 4, overrides: { TGroup: TGroup.Self, ap: 120 }, desc: "释放嗜血斩击,为{target}回复攻击力{ap}%生命" },
],
},
atked: {
// 坚硬皮肤:借 6513 防御爆发底座注入 7023 防御强化(+50%,可无限叠层)
6513: [
{ lv: 3, s_lv: SkillLv.Lv1, name: "坚硬皮肤", t_num: 2, overrides: { TGroup: TGroup.Self, timed_buff_id: 7023, buff_duration: 10 }, desc: "{target}防御提升{buff_value}%,持续{dur}秒" },
{ lv: 6, s_lv: SkillLv.Lv1, name: "坚硬皮肤", t_num: 2, overrides: { TGroup: TGroup.Self, timed_buff_id: 7023, buff_duration: 10 }, desc: "{target}防御提升{buff_value}%,持续{dur}秒" },
],
},
// card_lv 3:lv9 无光环,改为基础属性+50%
@@ -964,13 +1000,14 @@ export function resolveReviveByLv(revive: LvReviveEntry[] | undefined, lv: numbe
return pick ? { s_uuid: pick.s_uuid, r_num: pick.r_num, upr: pick.upr } : undefined;
}
/** 计算目标等级下额外属性加成(hp_bonus/ap_bonus 一次性奖励 + 成长类型每级递增) */
function getEvolveBonuses(hero: heroInfo, targetLv: number): { hp: number, ap: number } {
/** 计算目标等级下额外属性加成(hp/ap/def_bonus 一次性奖励 + 成长类型每级递增) */
function getEvolveBonuses(hero: heroInfo, targetLv: number): { hp: number, ap: number, def: number } {
const lv = Math.max(1, targetLv);
// 成长类型线性增量(仅英雄生效,怪物无 grow_type 时走 Warrior 基准但不影响平衡,因怪物通常不填)
const grow = hero.fac === FacSet.HERO ? calcGrowBonus(hero, lv) : { hp: 0, ap: 0 };
const grow = hero.fac === FacSet.HERO ? calcGrowBonus(hero, lv) : { hp: 0, ap: 0, def: 0 };
let hp = grow.hp;
let ap = grow.ap;
let def = grow.def;
if (hero.hp_bonus) {
for (const e of hero.hp_bonus) {
if (e.lv <= lv) hp += e.value;
@@ -981,15 +1018,57 @@ function getEvolveBonuses(hero: heroInfo, targetLv: number): { hp: number, ap: n
if (e.lv <= lv) ap += e.value;
}
}
return { hp, ap };
if (hero.def_bonus) {
for (const e of hero.def_bonus) {
if (e.lv <= lv) def += e.value;
}
}
return { hp, ap, def };
}
/** 计算目标等级下的有效 HP/AP(固定基础值 + 成长递增与一次性加成) */
function getEffectiveStats(hero: heroInfo, targetLv: number): { hp: number, ap: number } {
/** 计算目标等级下的有效 HP/AP/DEF(固定基础值 + 成长递增与一次性加成) */
export function getEffectiveStats(hero: heroInfo, targetLv: number): { hp: number, ap: number, def: number } {
const bonuses = getEvolveBonuses(hero, targetLv);
return {
hp: hero.hp + bonuses.hp,
ap: hero.ap + bonuses.ap,
def: hero.def + bonuses.def,
};
}
/**
* 计算英雄展示用最终属性(含品质系数与 lv12 职业专项),供 UI 面板与运行时对齐口径。
* 公式:基础值 × 品质系数 + 成长 + bonus,再叠加 lv12 专项(基数取 lv11 有效值)。
* @param hero 英雄配置
* @param targetLv 目标等级(≥1)
* @returns 含品质与专项的最终 hp/ap/def(已取整)
*/
export function getHeroDisplayStats(hero: heroInfo, targetLv: number): { hp: number, ap: number, def: number } {
const lv = Math.max(1, Math.floor(targetLv));
const coef = getHeroQualityCoef(hero.card_lv ?? 1);
const eff = getEffectiveStats(hero, lv);
const stats = {
hp: Math.round(hero.hp * coef) + (eff.hp - hero.hp),
ap: Math.round(hero.ap * coef) + (eff.ap - hero.ap),
def: Math.round(hero.def * coef) + (eff.def - hero.def),
};
// lv12 职业专项:基数为 lv11 展示有效值
if (lv >= HERO_LV12_SPECIAL_LV && hero.role !== undefined) {
const base11 = getHeroDisplayStatsBase(hero, HERO_LV12_BASE_LV);
const attr = HERO_LV12_SPECIAL_ATTR[hero.role];
stats[attr] += Math.round(base11[attr] * 0.5);
}
return stats;
}
/** 内部:lv12 专项基数(不含 lv12 自身)的展示有效值 */
function getHeroDisplayStatsBase(hero: heroInfo, targetLv: number): { hp: number, ap: number, def: number } {
const coef = getHeroQualityCoef(hero.card_lv ?? 1);
const eff = getEffectiveStats(hero, targetLv);
return {
hp: Math.round(hero.hp * coef) + (eff.hp - hero.hp),
ap: Math.round(hero.ap * coef) + (eff.ap - hero.ap),
def: Math.round(hero.def * coef) + (eff.def - hero.def),
};
}

View File

@@ -49,7 +49,8 @@ revive[0]:无
**通用约束**:
- lv2 走 atking/atked/fstart 提升普攻能力;lv3/5/7 走 `skills[1].lv_entries` 提升大招;lv9 光环或属性补偿
- 等级节奏:lv1 激活 skills[0]/skills[1];lv6 解锁 atking/atked/fstart 触发技能(1 个);大招(skills[1])lv9/lv16 走 `lv_entries` 分档提升;lv12 按职业对单项基础属性 +50%(基数取 lv11 当前等级有效值:坦克→def、战士/辅助→hp、刺客/射手/法师→ap);lv9 光环或属性补偿
- 品质差异:相邻品质(card_lv)lv1 初始基础属性(AP/HP/DEF)相差 5%(系数 1+0.05×(card_lv-1)),其余配置参数完全一致
- 能力只能从能力池(BuffList 7001\~7024 / FieldSkillSet 7001\~7020 / SkillSet 底座)引用 + `overrides` 数值覆盖,**禁止新增同义底座**
**大招召唤数约束**(`summon_count` 覆写规则):
@@ -303,11 +304,13 @@ revive[0]:无
## 配置检查清单
- [ ] `skills` 引用的 uuid 在 SkillSet 中存在,`overrides.ap` 显式写出
- [ ] 大招(`skills[1]`)覆写 `summon_count`:lv1=1、lv3=1、lv5=2、lv7=3,通过 `lv_entries` 逐级覆写,不改动 SkillSet 底座
- [ ] 大招(`skills[1]`)覆写 `summon_count`:lv1=1、lv9=1、lv16=2,通过 `lv_entries` 逐级覆写,不改动 SkillSet 底座
- [ ] `timed_buff_id` 指向 BuffList 已存在条目(能力池 2.1/2.2 内)
- [ ] debuff/buff 只通过 `overrides` 注入,未改动 SkillSet/BuffList 底座
- [ ] `atking`/`atked`/`fstart`/`dead` 按 s\_uuid 分组、按 lv 升序
- [ ] `atking`/`atked`/`fstart`/`dead` 按 s\_uuid 分组、按 lv 升序,触发技能统一 lv6 解锁
- [ ] lv9:card\_lv 4/5 配 `field`;card\_lv 1/2/3 配 `ap_bonus`/`hp_bonus`(30/40/50%)
- [ ] lv12:按职业注入单项属性 +50%(坦克 def、战士/辅助 hp、刺客/射手/法师 ap),基数取 lv11 有效值
- [ ] 品质:card\_lv 相邻基础属性差 5%(运行时品质系数统一乘,配置保持裸值)
- [ ] `t_num` 概率模拟符合预期(1=每次,3≈33%,4≈25%)
- [ ] `infos` 分级说明与配置档位一一对应(面板逐条展示)
- [ ] 近战/远程形态与 `type`/`dis` 匹配,美术资源 `path`/`icon` 就绪