返回小岛
技能市场/策划·程序/战斗公式建模师

战斗公式建模师

Community出品v1.0.0暂无评价8次安装

输入「游戏类型+PVP占比+养成周期」,输出伤害公式+PRD暴击+TTK/DPS/EHP验算

策划程序

combat-formula-modeler — 战斗公式建模 Skill

触发条件

当用户提到"战斗公式"、"伤害计算"、"数值建模"、"战斗数值"、"攻防公式"、"暴击系统"、"属性成长"、"TTK"、"DPS计算"、"数值验证"、"极端值压测"、"减伤建模"、"DPS平衡校验"时触发。 也适用于:用户说"帮我设计战斗公式"、"这个游戏用什么伤害公式好"、"做一下数值验证"、"成长曲线怎么设计"等场景。 当用户给出游戏类型并要求"搭数值框架"时,也应触发。

技能描述

帮助数值策划快速完成战斗数值体系搭建:输入游戏类型和基本需求,输出公式选型方案、参数建议、成长曲线、验证代码。融入微分方程建模方法论。


一、伤害公式选型引擎

决策流程

graph TD
    A[游戏类型?] --> B{PVP比重}
    B -->|重PVP/竞技| C{需要数值公平?}
    C -->|是| D[除法公式 — 收益递减]
    C -->|否| E[乘法多层公式]

    B -->|重PVE/RPG| F{数值膨胀周期}
    F -->|短周期 赛季制| G[减法公式 — 直观]
    F -->|长周期 永续| H{养成深度}
    H -->|浅 3个月达满| D
    H -->|深 6个月+| I[指数/幂函数公式]

    B -->|PVP+PVE并重| J[除法公式 + 等级压制系数]

    style D fill:#58a6ff22,stroke:#58a6ff
    style G fill:#3fb95022,stroke:#3fb950
    style I fill:#bc8cff22,stroke:#bc8cff
    style E fill:#d2992222,stroke:#d29922
    style J fill:#58a6ff22,stroke:#58a6ff

1.1 减法公式(线性防御)

公式

Damage = max(ATK × SkillRatio - DEF × DefCoeff, ATK × MinDmgRate)
参数含义建议范围
SkillRatio技能倍率1.0~5.0
DefCoeff防御系数0.5~1.0
MinDmgRate最低伤害比率0.05~0.15

适用品类:回合制RPG、早期卡牌、休闲战斗 优点:玩家直观理解"攻击力-防御力=伤害" 缺点:后期易出现"零伤"或"破防"极端;防御边际收益恒定 头部参考:早期勇者斗恶龙、梦幻西游基础伤害层

1.2 除法公式(收益递减防御)⭐ 最通用

公式

DamageReduction = DEF / (DEF + K)
Damage = ATK × SkillRatio × (1 - DamageReduction)
       = ATK × SkillRatio × K / (K + DEF)
参数含义调节效果
K(核心参数)防御基准常数K越大→防御越不值钱→偏攻击meta

K值速查表

K值DEF=100减伤DEF=300减伤DEF=500减伤适合的游戏风格
5066.7%85.7%90.9%防御为王,坦克职业明显
10050.0%75.0%83.3%平衡型(推荐起点)
20033.3%60.0%71.4%偏攻击,节奏较快
30025.0%50.0%62.5%攻击主导,秒人快
50016.7%37.5%50.0%极端攻击meta

K值动态化(等级关联)

K = K_base + K_growth × Level
// 例:K = 100 + 5 × Level
// 随等级提升,防御的边际价值缓慢降低

适用品类:MOBA、ARPG、大部分现代手游 头部参考:英雄联盟(K≈100)、王者荣耀、原神防御层

1.3 乘法多层公式(独立叠乘)

公式

FinalDamage = BaseDamage
    × (1 - ArmorReduction)      // 物理减伤层
    × (1 - MagicResistReduction) // 法术抗性层
    × (1 - DamageReduction)      // 通用减伤层
    × (1 + DamageBonus)          // 增伤层
    × ElementMultiplier          // 属性克制

特点:各层独立计算,永远不会100%减伤 适用品类:暗黑like、POE、复杂养成ARPG 头部参考:暗黑破坏神系列、流放之路

1.4 指数/幂函数公式

公式

Damage = ATK × (ATK / DEF) ^ n × SkillRatio
// 或
Damage = ATK × e^(-DEF / K)
n值效果适用场景
0.3~0.5温和的攻防差距影响竞技类,不想拉大差距
0.5~0.7中等差距影响RPG主流
0.7~1.0强烈的等级碾压感强调等级/装备压制

适用品类:强调等级压制的MMO、SLG 头部参考:DNF(攻防差明显影响输出)


二、暴击系统设计

2.1 暴击期望公式

E(Damage) = BaseDamage × (1 + CritRate × (CritDamage - 1))

最优配比法则:暴击率:暴击伤害获取成本 = 1:2 时,期望伤害最大化

  • 引导方式:让暴击率装备和暴击伤害装备的属性密度满足这个比例

2.2 纯随机暴击

import random

def pure_random_crit(base_damage, crit_rate, crit_damage):
    if random.random() < crit_rate:
        return base_damage * crit_damage
    return base_damage

问题:手感差,可能连续10次暴击或10次不暴击

2.3 PRD伪随机(推荐)⭐

DOTA2 风格伪随机分布,保持期望不变但减少极端情况:

class PRDCrit:
    """伪随机暴击系统 — 保底+防连击"""

    # 名义暴击率 → PRD初始概率C的映射表
    C_TABLE = {
        0.05: 0.003802, 0.10: 0.014746, 0.15: 0.032221,
        0.20: 0.055704, 0.25: 0.084744, 0.30: 0.118949,
        0.35: 0.157983, 0.40: 0.201547, 0.45: 0.249306,
        0.50: 0.302103, 0.55: 0.360397, 0.60: 0.422649,
        0.65: 0.481523, 0.70: 0.571429, 0.75: 0.666667,
    }

    def __init__(self, nominal_rate: float):
        self.nominal_rate = nominal_rate
        self.c = self._get_c(nominal_rate)
        self.fail_count = 0

    def _get_c(self, rate):
        """插值获取C值"""
        keys = sorted(self.C_TABLE.keys())
        for i in range(len(keys) - 1):
            if keys[i] <= rate <= keys[i+1]:
                t = (rate - keys[i]) / (keys[i+1] - keys[i])
                return self.C_TABLE[keys[i]] * (1-t) + self.C_TABLE[keys[i+1]] * t
        return rate  # fallback

    def try_crit(self) -> bool:
        """尝试暴击,返回是否暴击"""
        import random
        self.fail_count += 1
        prob = self.c * self.fail_count
        if random.random() < prob:
            self.fail_count = 0
            return True
        return False

# 使用示例
crit = PRDCrit(0.25)  # 25%名义暴击率
results = [crit.try_crit() for _ in range(10000)]
print(f"实际暴击率: {sum(results)/len(results):.2%}")  # ≈25%

2.4 暴击率计算方式

基于属性的暴击率(收益递减型)

CritRate = CritValue / (CritValue + K_crit)
// K_crit 决定暴击率的获取难度
// 例:K_crit=1000,CritValue=500 → 暴击率=33.3%

暴击率上限:建议设置 75%~85% 硬上限,避免暴击率100%


三、属性成长曲线

3.1 曲线类型选择器

曲线类型公式前期中期后期适用
线性a × L + b匀速匀速匀速简单系统
二次方a × L² + b最常用·通用
三次方a × L³ + b很慢很快长线养成
指数a × r^L很慢爆炸赛季制/无限等级
对数a × ln(L) + b极慢快速到达体验
S型L_max / (1+e^(-k(L-L0)))有上限的系统
分段(实战最优)各段独立公式自定义自定义自定义手游推荐

3.2 分段经验曲线模板

def exp_required(level: int) -> int:
    """分段经验需求 — 手游标准三段式"""
    if level <= 30:
        # 快速成长期:让玩家2周内到30级
        return int(50 * level ** 1.5)
    elif level <= 60:
        # 稳定成长期:30→60需要约1.5个月
        return int(200 * level ** 2)
    else:
        # 缓慢成长期:60→100需要3个月+
        return int(500 * level ** 2.5)

# 打印经验表
for lv in [1,10,20,30,40,50,60,70,80,90,100]:
    print(f"Lv.{lv:3d} → {exp_required(lv):>12,} EXP")

3.3 属性成长模板

def attribute_growth(base, growth, level, quality_mult=1.0):
    """
    通用属性成长公式
    base: 1级基础值
    growth: 每级成长值
    level: 当前等级
    quality_mult: 品质系数 (B=0.8, A=1.0, S=1.2, SS=1.5, SSS=2.0)
    """
    return int((base + growth * (level - 1)) * quality_mult)

# 品质差异化示例
qualities = {'B': 0.8, 'A': 1.0, 'S': 1.2, 'SS': 1.5, 'SSS': 2.0}
for q, mult in qualities.items():
    atk = attribute_growth(base=100, growth=12, level=60, quality_mult=mult)
    print(f"{q:>3s}级 Lv.60 ATK = {atk}")

四、战斗模拟验证

4.1 核心验证指标

指标公式健康范围说明
TTK (Time to Kill)目标HP ÷ DPSPVP: 38秒, PVE: 1030秒击杀时间
DPS (每秒输出)E(单次伤害) × 攻速持续输出能力
EHP (有效生命)HP × (1 + DEF/K)考虑防御后的等效血量
TTK比最高TTK ÷ 最低TTK< 3.0职业间平衡度
输出差最高DPS ÷ 最低DPS< 2.5同等级/装备下的差距
治疗压力秒伤 ÷ 秒治疗0.6~0.8团队战斗节奏

4.2 Python 战斗模拟器

import random
from dataclasses import dataclass

@dataclass
class Fighter:
    name: str
    hp: int
    atk: int
    defense: int  # 'def' is reserved
    crit_rate: float = 0.2
    crit_damage: float = 1.5
    atk_speed: float = 1.0  # 攻击/秒

class BattleSimulator:
    """简易战斗模拟器 — 除法公式"""

    def __init__(self, K=100):
        self.K = K

    def calc_damage(self, attacker: Fighter, defender: Fighter) -> float:
        """单次伤害计算"""
        reduction = defender.defense / (defender.defense + self.K)
        base_dmg = attacker.atk * (1 - reduction)
        # 暴击判定
        if random.random() < attacker.crit_rate:
            base_dmg *= attacker.crit_damage
        # 随机浮动 ±5%
        base_dmg *= random.uniform(0.95, 1.05)
        return max(base_dmg, 1)

    def simulate_duel(self, a: Fighter, b: Fighter, rounds=1000):
        """模拟对战,返回统计结果"""
        a_wins = 0
        total_turns_list = []

        for _ in range(rounds):
            hp_a, hp_b = a.hp, b.hp
            turns = 0
            while hp_a > 0 and hp_b > 0:
                turns += 1
                # A 攻击 B
                hp_b -= self.calc_damage(a, b)
                if hp_b <= 0:
                    a_wins += 1
                    break
                # B 攻击 A
                hp_a -= self.calc_damage(b, a)
            total_turns_list.append(turns)

        avg_turns = sum(total_turns_list) / len(total_turns_list)
        return {
            'a_win_rate': a_wins / rounds,
            'b_win_rate': 1 - a_wins / rounds,
            'avg_turns': avg_turns,
            'avg_ttk_seconds': avg_turns / max(a.atk_speed, b.atk_speed),
        }

    def calc_ehp(self, fighter: Fighter) -> float:
        """计算有效生命值"""
        return fighter.hp * (1 + fighter.defense / self.K)

    def calc_expected_dps(self, fighter: Fighter, target: Fighter) -> float:
        """计算期望DPS"""
        reduction = target.defense / (target.defense + self.K)
        base_dmg = fighter.atk * (1 - reduction)
        crit_mult = 1 + fighter.crit_rate * (fighter.crit_damage - 1)
        return base_dmg * crit_mult * fighter.atk_speed

# === 使用示例 ===
if __name__ == '__main__':
    sim = BattleSimulator(K=100)

    warrior = Fighter('战士', hp=5000, atk=300, defense=200, crit_rate=0.15, crit_damage=1.5)
    mage    = Fighter('法师', hp=3000, atk=500, defense=80,  crit_rate=0.25, crit_damage=2.0)
    tank    = Fighter('坦克', hp=8000, atk=150, defense=400, crit_rate=0.05, crit_damage=1.5)

    roles = [warrior, mage, tank]

    print("=== 有效生命值(EHP) & 期望DPS ===")
    for r in roles:
        ehp = sim.calc_ehp(r)
        for target in roles:
            if target != r:
                dps = sim.calc_expected_dps(r, target)
                ttk = target.hp / dps if dps > 0 else float('inf')
                print(f"{r.name} vs {target.name}: DPS={dps:.0f}, TTK={ttk:.1f}s")
        print(f"{r.name} EHP={sim.calc_ehp(r):.0f}")
        print()

    print("=== 对战模拟 (1000回合) ===")
    for i, a in enumerate(roles):
        for b in roles[i+1:]:
            result = sim.simulate_duel(a, b)
            print(f"{a.name} vs {b.name}: "
                  f"胜率 {result['a_win_rate']:.1%} / {result['b_win_rate']:.1%}, "
                  f"平均回合 {result['avg_turns']:.1f}")

4.3 验证检查清单

  • 同等级同装备的不同职业,TTK差异 < 3倍
  • 高10级打低10级,TTK < 正常TTK的30%(等级压制明显但不秒杀)
  • 纯堆防御的极端Build,仍然可以被击杀(EHP不超过正常的5倍)
  • 纯堆攻击的极端Build,TTK > 2秒(不能秒杀)
  • 暴击系统不会出现连续5次以上暴击(使用PRD)
  • 治疗量 < 同等级DPS的80%(治疗不能完全抵消伤害)
  • 等级×10的差距内,低等级仍有胜算(> 20%胜率)

五、微分方程建模方法论

核心思想来源于《游戏数学建模工程手册》:游戏的数值系统本质上是一个动态系统,可以用微分方程描述其状态随时间的变化。

5.1 核心建模范式

玩家战力成长 = 微分方程的解曲线

dP/dt = f(t, P, R)

P = 玩家战力 (Power)
t = 游戏时间 (天)
R = 资源投入速率 (每日获取资源量)
f = 成长函数 (由养成系统决定)

5.2 三种典型成长模型

模型A:线性成长(匀速养成)

dP/dt = c (常数)
P(t) = c × t + P₀

适合:休闲游戏、赛季初期

模型B:指数成长(加速养成)

dP/dt = k × P
P(t) = P₀ × e^(kt)

适合:SLG前期扩张、卡牌等级成长

模型C:逻辑斯谛成长(S型·有上限) ⭐推荐

dP/dt = r × P × (1 - P/P_max)
P(t) = P_max / (1 + ((P_max - P₀)/P₀) × e^(-rt))

适合:有明确战力天花板的游戏,中期成长最快,自然减速

5.3 经济系统的微分方程

资源存量动态

dS/dt = Production(t) - Consumption(S, t)

S = 资源存量
Production = 产出速率(随等级/VIP提升)
Consumption = 消耗速率(随养成进度增加)

通胀判定:当 dS/dt > 0 持续超过 N 天,系统进入通胀状态 紧缩判定:当 dS/dt < 0 持续超过 N 天,玩家体验产出匮乏

5.4 实践应用:用ODE拟合验证数值表

from scipy.integrate import odeint
import numpy as np

def growth_model(P, t, r, P_max):
    """逻辑斯谛成长模型"""
    return r * P * (1 - P / P_max)

# 参数
P0 = 100        # 初始战力
P_max = 50000   # 战力上限
r = 0.05        # 成长速率
t = np.linspace(0, 180, 181)  # 180天

# 求解ODE
P = odeint(growth_model, P0, t, args=(r, P_max))

# 打印关键节点
for day in [7, 14, 30, 60, 90, 120, 150, 180]:
    print(f"第{day:3d}天: 战力 = {P[day][0]:,.0f} ({P[day][0]/P_max*100:.1f}%)")

六、元素/属性克制系统

6.1 克制矩阵模板

三属性环(最简)

火 → 冰 → 雷 → 火
克制倍率:1.5x   被克倍率:0.67x   同属性:1.0x

五行环(仙侠/武侠)

金 → 木 → 土 → 水 → 火 → 金
克制倍率:1.3x   被克倍率:0.75x

多属性矩阵(复杂型,如宝可梦)

攻\防
0.50.52.01.02.01.0
2.00.50.51.01.02.0
0.52.00.51.01.02.0
1.02.00.50.51.00.0

双属性防御时:倍率相乘(4x超效/0.25x抵抗/0x免疫均可能出现)

6.2 反应体系(原神风格)

增幅反应(蒸发/融化):
FinalDamage = BaseDamage × ReactionMult × (1 + EM_Bonus)
ReactionMult = 1.5(弱增幅)或 2.0(强增幅)
EM_Bonus = 2.78 × EM / (EM + 1400)

剧变反应(超载/感电/扩散):
FinalDamage = LevelBaseDamage × ReactionCoeff × (1 + EM_Bonus)
// 独立于攻击力,只与等级和精通有关

6.3 平衡性验证方法

def verify_element_balance(matrix):
    """验证克制矩阵是否存在绝对优势属性"""
    n = len(matrix)
    for i in range(n):
        advantage_count = sum(1 for j in range(n) if matrix[i][j] > 1.0)
        disadvantage_count = sum(1 for j in range(n) if matrix[i][j] < 1.0)
        ratio = advantage_count / max(disadvantage_count, 1)
        if ratio > 2.0:
            print(f"⚠️ 属性{i}克制比过高({ratio:.1f}),可能存在优势属性")
        print(f"属性{i}: 克制{advantage_count}个 / 被克{disadvantage_count}个, 比率={ratio:.1f}")

七、治疗/护盾/控制机制

7.1 治疗公式

基础治疗

HealAmount = HealPower × SkillRatio + FlatHeal

暴击治疗(允许治疗暴击时):

if random() < CritRate:
    HealAmount *= CritHealMult  // 通常 1.25~1.5(低于伤害暴击倍率)

治疗衰减(防止无限续航):

// 超量治疗递减:同一回合内第N次治疗效果衰减
EffectiveHeal = HealAmount × 0.8^(N-1)
// 第1次100%、第2次80%、第3次64%...

7.2 护盾公式

ShieldValue = ShieldPower × SkillRatio + FlatShield
ShieldDuration = BaseDuration  // 通常 5~10秒

护盾吸收:先扣护盾,护盾破碎后溢出伤害才扣血
EffectiveDamage = max(0, Damage - CurrentShield)
CurrentShield = max(0, CurrentShield - Damage)

护盾衰减(防止无限叠盾):

// 方案A:护盾不可叠加,新盾替换旧盾(取较大值)
// 方案B:护盾叠加但总量不超过MaxHP的50%
MaxShield = MaxHP × 0.5

7.3 控制机制公式

控制时长 = BaseControlDuration × (1 - Tenacity/100)
Tenacity = 韧性属性(0~75,75%为减控上限)

// 递减控制(MOBA常用):
// 短时间内连续受控时,后续控制时长递减
EffectiveDuration = BaseDuration × 0.7^(RecentControlCount)

7.4 治疗压力指标

指标公式健康范围说明
治疗压力比TeamDPS ÷ TeamHPS1.2~1.8<1.0=治疗过强 >2.5=治疗无意义
续航回合数TeamHP ÷ (IncomingDPS - TeamHPS)8~15回合团队在受攻击下能存活的回合数

八、等级压制系数

公式

LevelSuppression = clamp(1 - SuppRate × (DefLevel - AtkLevel), 0.1, 1.5)

SuppRate = 0.03~0.08(每级压制率)
- 0.03: 温和压制(竞技向,10级差=30%衰减)
- 0.05: 标准压制(RPG常用,10级差=50%衰减)
- 0.08: 强力压制(强PVE等级墙,10级差=80%衰减)

FinalDamage = BaseDamage × LevelSuppression

示例(SuppRate=0.05)

等级差(攻-防)压制系数效果
+101.50(上限)碾压,伤害×1.5
+51.25明显优势
01.00公平对战
-50.75明显劣势
-100.50重度劣势
-200.10(下限)几乎无法造成伤害

九、配表模板

角色属性表

角色ID角色名品质初始HPHP成长初始ATKATK成长初始DEFDEF成长暴击率暴击伤害攻速
1001战士S120018010012801010%150%1.0
1002法师S8001001601840520%180%0.8
1003坦克A1800250606120165%130%0.7
1004刺客SS700851401635430%200%1.5
1005治疗A9001208086088%140%1.0

等级经验表

等级所需经验累计经验预计天数HP系数ATK系数DEF系数
10001.001.001.00
101,5818,50021.451.451.45
204,47242,00051.901.901.90
308,216110,000102.352.352.35
分段切换点:Lv.31起使用二次方公式 200×L²,经验需求大幅跃升
40320,000850,000202.802.802.80
501,000,0003,200,000353.253.253.25
601,440,0007,800,000553.703.703.70

七、输出规范

使用本 Skill 时,按以下结构输出数值方案:

# [游戏名称] 战斗数值设计方案

## 1. 项目信息
- 游戏类型、战斗节奏、PVP/PVE比重、等级上限、养成周期

## 2. 伤害公式
- 选型依据
- 完整公式 + 各参数说明
- 公式曲线图(描述或Python绘制)

## 3. 暴击/命中/闪避系统
- 各系统公式 + 参数
- 是否使用PRD

## 4. 属性成长表
- 角色属性配表
- 等级经验表
- 成长曲线类型和参数

## 5. 战斗模拟验证
- TTK / DPS / EHP 指标表
- 职业对战胜率矩阵
- 等级压制验证
- Python验证代码

## 6. 验证结论
- 对照检查清单的逐项结果
- 需要调优的参数建议

## 7. 下游交接物
- 交付给UI拆解师:角色属性面板展示字段清单、战斗HUD数据接口(血条/蓝条/技能CD/伤害数字格式)、属性克制关系图
- 交付给架构师:战力计算公式、养成线数值区间、各系统战力占比