原神增幅反应伤害期望公式¶

泡茶的小原课堂

$$E = \underbrace{\left( A \times \frac{M}{100} + B \right)}_{\substack{\text{基础区} \\ \scriptscriptstyle A:\text{面板攻击力} \\ \scriptscriptstyle M:\text{技能倍率} \\ \scriptscriptstyle B:\text{固定加成}}} \times \underbrace{\left( 1 + \frac{C_r}{100} \times \frac{C_d}{100} \right)}_{\substack{\text{双暴区} \\ \scriptscriptstyle C_r:\text{暴击率} \\ \scriptscriptstyle C_d:\text{暴击伤害}}} \times \underbrace{\left( 1 + \frac{D_b}{100} \right)}_{\substack{\text{增伤区} \\ \scriptscriptstyle D_b:\text{元素/物理增伤}}} \times \underbrace{\begin{cases} 1 + \frac{|R_p|}{200} & R_p < 0 \\ 1 - \frac{R_p}{100} & 0 \leq R_p \leq 75 \\ \frac{1}{1 + \frac{4 \times R_p}{100}} & R_p > 75 \end{cases}}_{\substack{\text{抗性区} \\ \scriptscriptstyle R_p = R_m - R_c \\ \scriptscriptstyle R_m:\text{怪物抗性} \\ \scriptscriptstyle R_c:\text{角色减抗}}} \times \underbrace{\frac{L_c + 100}{(L_m + 100)(1 - D_p/100) + L_c + 100}}_{\substack{\text{防御区} \\ \scriptscriptstyle L_c:\text{角色等级} \\ \scriptscriptstyle L_m:\text{敌人等级} \\ \scriptscriptstyle D_p:\text{减防数值}}} \times \underbrace{M_s \times \left(1 + \frac{278 \times E_m}{100 \times (E_m + 1400)}\right)}_{\substack{\text{反应区} \\ \scriptscriptstyle M_s:\text{反应系数} \\ \scriptscriptstyle E_m:\text{精通值}}}$$

【Python】基于多区乘算模型的原神战斗系统计算:角色属性管理 × 反应伤害计算 × 额外词条收益¶

  • 此处以角色玛薇卡(玛希茜班配队)坠日斩后满buff5融手法实战举例(详细可查阅BV1P6oUYFE3H):
In [5]:
import copy
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import make_interp_spline


# 全局中文支持配置
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False


class Character:
    """角色属性与状态管理类"""

    def __init__(self, data):
        self.name = data["角色名"]
        self.attack = data["面板攻击力值"]  # 面板攻击力
        self.base_attack = data["基础攻击力值"]  # 基础攻击力(白字)
        self.amplify_multiplier = data["增幅反应倍率值"]  # 增幅反应倍率(%)
        self.normal_multiplier = data["常规倍率值"]  # 常规攻击倍率(%)
        self.base_bonus = data["基础加成值"]  # 固定加成值(e.g. 申鹤、云堇...)
        self.crit_rate = data["暴率值"]  # 暴击率(%)
        self.crit_dmg = data["暴伤值"]  # 暴击伤害(%)
        self.dmg_bonus = data["增伤值"]  # 增伤系数(%)
        self.res_pen = data["减抗值"]  # 抗性穿透(%)
        self.def_pen = data["减防值"]  # 防御穿透(%)
        self.level = data["角色等级"]  # 角色等级
        self.em = data["精通值"]  # 元素精通值
        self.react_coeff = data["反应系数"]  # 反应系数


class Enemy:
    """怪物属性管理类"""

    def __init__(self, data):
        self.resistance = data["怪物抗性值"]  # 元素抗性(%)
        self.level = data["怪物等级"]  # 怪物等级


class DamageCalculator:
    """伤害计算引擎"""

    def __init__(self, character, enemy):
        self.char = character
        self.enemy = enemy

    def _base_damage(self, multiplier):
        """基础攻击区计算"""
        return self.char.attack * (multiplier / 100) + self.char.base_bonus

    def _crit_multiplier(self):
        """暴伤区计算"""
        return (100 + self.char.crit_dmg) / 100

    def _elemental_bonus(self):
        """增伤区计算"""
        return (100 + self.char.dmg_bonus) / 100

    def _resistance_adj(self):
        """抗性穿透计算"""
        res = self.enemy.resistance - self.char.res_pen
        if res < 0:
            return 1 - res / 200
        return 1 - res / 100 if res <= 75 else 1 / (1 + (res * 4)/100)

    def _defense_adj(self):
        """防御穿透计算"""
        return (self.char.level + 100) / (
            (self.enemy.level + 100) * (1 - self.char.def_pen / 100)
            + self.char.level
            + 100
        )

    def _mastery_bonus(self):
        """精通增幅区计算"""
        return self.char.react_coeff * (1 + (278 * self.char.em / (self.char.em + 1400)) / 100)
    

class AmplifyDamageCalculator(DamageCalculator):
    """增幅反应伤害计算引擎"""

    def calculate(self):
        """增幅反应伤害计算"""
        base = self._base_damage(self.char.amplify_multiplier)
        return round(
            base
            * self._crit_multiplier()
            * self._elemental_bonus()
            * self._resistance_adj()
            * self._defense_adj()
            * self._mastery_bonus()
        )

    def expectation(self):
        """期望伤害计算"""
        crit_rate = self.char.crit_rate / 100
        return round(self.calculate() * crit_rate)


class NormalDamageCalculator(DamageCalculator):
    """常规伤害计算引擎"""

    def calculate(self):
        """常规伤害计算"""
        base = self._base_damage(self.char.normal_multiplier)
        return round(
            base
            * self._crit_multiplier()
            * self._elemental_bonus()
            * self._resistance_adj()
            * self._defense_adj()
        )

    def expectation(self):
        """期望伤害计算"""
        crit_rate = self.char.crit_rate / 100
        return round(self.calculate() * crit_rate)
    

class AttributeGainSimulator:
    """额外属性增益模拟计算器"""
    
    def __init__(self, character, enemy):
        self.character = character  # 基础角色实例
        self.enemy = enemy  # 敌人实例
        
    def _create_character(self, attr_type, n):
        """创建带指定增益的角色实例"""
        char = copy.deepcopy(self.character)
        
        if attr_type == '攻击':
            added_attack = self.character.base_attack * 0.05 * n
            char.attack += added_attack
        elif attr_type == '爆伤':
            char.crit_dmg += 6.6 * n
        elif attr_type == '增伤':
            char.dmg_bonus += 5 * n
        elif attr_type == '精通':
            char.em += 20 * n
        
        return char
    
    def generate_data(self, max_stacks=100):
        """生成各属性的模拟增幅数据"""
        base_dmg = self._get_base_damage()
        results = {
            '攻击': [],
            '爆伤': [],
            '增伤': [],
            '精通': []
        }
        
        for n in range(max_stacks+1):
            for attr in results.keys():
                char = self._create_character(attr, n)
                calc = AmplifyDamageCalculator(char, self.enemy).expectation() + NormalDamageCalculator(char, self.enemy).expectation()
                results[attr].append((calc / base_dmg - 1) * 100)
                
        return results
    
    def _get_base_damage(self):
        """获取0词条时的基准伤害"""
        base_char = self._create_character('攻击', 0)  # 0词条状态
        return AmplifyDamageCalculator(base_char, self.enemy).expectation() + NormalDamageCalculator(base_char, self.enemy).expectation()


class AttributeGainVisualizer:
    """模拟伤害增幅数据可视化器"""
    
    def __init__(self, data, character):
        self.data = data
        self.character = character
        
    def plot_curves(self, save_path=None):
        """绘制增益曲线图"""
        plt.figure(figsize=(14, 10))
        colors = {'攻击': '#E74C3C', '爆伤': '#3498DB', 
                 '增伤': '#2ECC71', '精通': '#9B59B6'}
        
        x = np.arange(0, len(self.data['攻击']))
        for attr, values in self.data.items():
            # 添加样条插值平滑曲线
            spline = make_interp_spline(x, values, k=3)
            x_smooth = np.linspace(0, max(x), 500)
            y_smooth = spline(x_smooth)
            
            plt.plot(x_smooth, y_smooth, 
                    label=attr, 
                    color=colors[attr], 
                    linewidth=2.5,
                    alpha=0.8)

        # 样式设置
        plt.title(f'常规属性词条收益对比({self.character.name})', fontsize=14, pad=20, fontweight='bold')
        plt.xlabel('增益词条数(1词条 = 6.6%爆伤 = 5%攻击 = 5%增伤 = 20精通)', fontsize=12, labelpad=10)
        plt.ylabel('伤害增幅 (%)', fontsize=12, labelpad=10)
        plt.grid(True, alpha=0.2, linestyle='--')
        plt.legend(title="增益属性", title_fontsize=12, fontsize=10, loc='upper left', frameon=True, shadow=True)
        
        # 刻度设置
        plt.xticks(np.arange(0, len(x)+1, 2), [f'+{i}' for i in np.arange(0, len(x)+1, 2)])
        plt.gca().spines['top'].set_visible(False)
        plt.gca().spines['right'].set_visible(False)
        plt.tight_layout()
        if save_path:
            plt.savefig(
                save_path,
                dpi=300,
                bbox_inches="tight",
                facecolor="white"
            )
        plt.show()


if __name__ == "__main__":
    # 创建角色信息列表(玛希班茜)
    data = {
        "角色名": "玛薇卡5融——满能量启动",
        "面板攻击力值": 7098,
        "基础攻击力值": 1299,
        "增幅反应倍率值": 1 * (945.2 + 120 + 200 * 3.4) + 4 * (236.9 + 90 + 200 * 1.236),
        "常规倍率值": 3 * 500 + 4 * (236.9 + 90 + 200 * 1.236),
        "基础加成值": (1 + 4 + 3 + 4) * 2 * 725 + (6) * 0.65 * 4385,
        "暴率值": 98,
        "暴伤值": 268,
        "增伤值": 127.2 + 50 + 15,
        "减抗值": 40 + 45,
        "怪物抗性值": 10,
        "减防值": 20,
        "角色等级": 90,
        "怪物等级": 103,
        "精通值": 161 + 120 + 250,
        "反应系数": 2,
    }

    # 多态计算不同伤害类型
    character = Character(data)
    enemy = Enemy(data)
    amp_calculator = AmplifyDamageCalculator(character, enemy)
    normal_calculator = NormalDamageCalculator(character, enemy)

    # 输出伤害计算结果
    print("===================================================")
    print(f"【{character.name}】增幅反应伤害:{amp_calculator.calculate()},期望:{amp_calculator.expectation()}")
    print(f"【{character.name}】常规伤害:{normal_calculator.calculate()},期望:{normal_calculator.expectation()}")
    print(f"【{character.name}】总计伤害:{amp_calculator.calculate() + normal_calculator.calculate()},期望:{amp_calculator.expectation() + normal_calculator.expectation()}")
    print("===================================================\n")

    # 可视化展示额外属性增益模拟
    simulator = AttributeGainSimulator(character, enemy)
    result_data = simulator.generate_data()
    visualizer = AttributeGainVisualizer(result_data, character)
    visualizer.plot_curves()
===================================================
【玛薇卡5融——满能量启动】增幅反应伤害:9040706,期望:8859892
【玛薇卡5融——满能量启动】常规伤害:2423143,期望:2374680
【玛薇卡5融——满能量启动】总计伤害:11463849,期望:11234572
===================================================

No description has been provided for this image