Skip to content

# 枪械六大核心属性通用计算公式文档

# 1. 基础强度 Firepower (范围: 0-100)

定义: 表示武器每秒能造成的伤害总量,反映持续火力强度。

计算公式:

Firepower = (Base_Damage × Shots_Per_Second) × (1 - 平均伤害衰减比例)

基于YML配置的公式:

Firepower = ({Weapon.Damage.Base_Damage} × {Weapon.Shoot.Fully_Automatic_Shots_Per_Second}) × (1 - 平均伤害衰减比例)

参数说明:

  • Base_Damage: 武器基础伤害值
  • Shots_Per_Second: 每秒射击次数(射速)
  • 平均伤害衰减比例: 根据不同距离的伤害衰减计算得出的平均值

标准化处理:

标准化Firepower = MIN(100, MAX(0, Firepower))
对于火箭发射器

基于火箭武器瞬时爆发、范围伤害和低射速的特点,设计了专用的Firepower定义和计算公式:


# 火箭武器专用 Firepower 定义 (范围: 0-100)

定义: 表示武器单次射击造成的等效秒伤(DPS),综合爆炸范围伤害、装填时间和范围效能,反映爆发火力强度。

计算公式:

math
Firepower = \frac{ (Base\_Damage + Base\_Explosion\_Damage \times Effective\_Targets) \times Damage\_Multipliers }{ Reload\_Time }

基于YML配置的公式:

Firepower = (
({Weapon.Damage.Base_Damage} + {Weapon.Damage.Base_Explosion_Damage} × {Weapon.Explosion.Effective_Targets})
× (1 + {Weapon.Damage.Fire_Ticks} × 0.01)
) / {Weapon.Shoot.Reload_Time}

参数说明:

参数说明
Base_Damage直接命中伤害值
Base_Explosion_Damage爆炸基础伤害值
Effective_Targets爆炸有效目标数,根据爆炸半径计算:MIN(5, (Explosion_Radius² / 4))
Damage_Multipliers伤害增益系数,包含:
- 燃烧增益:1 + (Fire_Ticks × 0.01)
- 负面效果增益(如眩晕/中毒):+0.1/效果
Reload_Time装填时间(秒),火箭武器核心参数

标准化处理:

标准化Firepower = MIN(100, MAX(0, Firepower))

# 多发火箭系统扩展公式

定义: 单次触发发射多枚火箭时的聚合火力强度

计算公式:

math
Firepower = \frac{ Missile\_Count \times (Base\_Damage + Base\_Explosion\_Damage \times Effective\_Targets \times Spread\_Factor) \times Damage\_Multipliers }{ Cluster\_Reload\_Time }

基于YML配置的公式:

Firepower = (
{Weapon.Shoot.Missile_Count}
× ({Weapon.Damage.Base_Damage} + {Weapon.Damage.Base_Explosion_Damage} × {Weapon.Explosion.Effective_Targets} × {Weapon.Explosion.Spread_Factor})
× (1 + {Weapon.Damage.Fire_Ticks} × 0.01)
) / {Weapon.Shoot.Cluster_Reload_Time}

新增参数说明:

参数说明典型值
Missile_Count单次发射火箭数量3(三联装), 6(蜂窝式)
Spread_Factor散布补偿系数0.7 + (0.3 / Missile_Count)
解决多弹重叠伤害衰减
三联装:0.8
六联装:0.75
Cluster_Reload_Time集群装填时间Base_Reload_Time × (0.5 + 0.5 × Missile_Count)
反映多弹装填效率
-


# 2. 弹道精度 Accuracy (范围: 0-100)

定义: 反映射击时子弹散布控制程度,数值越高表示精度越好。

计算公式:

Accuracy = MAX(0, 100 - (Base_Spread × 精度系数))

基于YML配置的公式:

Accuracy = MAX(0, 100 - ({Weapon.Shoot.Spread.Base_Spread} × 精度系数))

参数说明:

  • Base_Spread: 基础散布值
  • 精度系数: 根据游戏平衡调整的倍数(建议范围10-20)

考虑不同状态下的精度修正:

最终Accuracy = Accuracy × (1 + 瞄准时精度加成 + 蹲伏时精度加成 - 跳跃时精度惩罚)

# 3. 操控性能 Stability (范围: 0-100)

定义: 衡量后坐力累积和恢复的速度,决定连续射击中的可控性。

计算公式:

Stability = 100 - (Recoil_Accumulation × 累积系数 + Recoil_Speed × 速度系数)

基于YML配置的公式:

Stability = 100 - ({Weapon.Shoot.Recoil.Max_Accumulation} × 累积系数 + {Weapon.Shoot.Recoil.Speed} × 速度系数)

参数说明:

  • Recoil_Accumulation: 后坐力最大累积值
  • Recoil_Speed: 后坐力上升速度
  • 累积系数: 后坐力累积对稳定性的影响权重
  • 速度系数: 后坐力速度对稳定性的影响权重

# 4. 移动速度 Mobility (范围: 0-50)

定义: 衡量使用武器时对玩家移动速度的影响,越高越好。

计算公式:

Mobility = MAX(0, 50 + (movement_speed_modifier × 速度系数))

基于YML配置的公式:

Mobility = MAX(0, 50 + ({Weapon.Item.Attributes.movement_speed} × 速度系数))

参数说明:

  • movement_speed_modifier: 武器对移动速度的修正值(通常为负值)
  • 速度系数: 将速度修正转换为属性值的倍数(建议1000-2000)

标准化处理:

标准化Mobility = MIN(50, MAX(0, Mobility))

# 5. 换弹速度 Reload_Speed (范围: 0-50)

定义: 衡量换弹时间的快慢,数值越高表示换弹越快。

计算公式:

Reload_Speed = MAX(0, 50 - Reload_Duration / 时间系数)

基于YML配置的公式:

Reload_Speed = MAX(0, 50 - {Weapon.Reload.Reload_Duration} / 时间系数)

参数说明:

  • Reload_Duration: 换弹持续时间(以游戏刻度为单位)
  • 时间系数: 将换弹时间转换为属性值的除数(建议范围1-3)

标准化处理:

标准化Reload_Speed = MIN(50, MAX(0, Reload_Speed))

# 6. 有效射程 Effective_Range (范围: 0-100)

定义: 根据伤害衰减情况估算有效打击距离。

计算公式:

Effective_Range = 100 - (最大伤害衰减距离 / 最大射程 × 100)

基于YML配置的公式:

Effective_Range = 100 - ({Weapon.Damage.Dropoff.最大距离} / 最大射程 × 100)

参数说明:

  • 最大伤害衰减距离: 伤害开始显著下降的距离(从Damage.Dropoff中提取)
  • 最大射程: 武器的最大射击距离

简化计算:

Effective_Range = (有效射程距离 / 最大射程) × 100

标准化处理:

标准化Effective_Range = MIN(100, MAX(0, Effective_Range))

# 通用属性计算注意事项

  1. 数值范围控制: 所有属性值必须在指定范围内,超出范围时应进行截断处理
  2. 系数调整: 各公式中的系数需要根据实际游戏平衡进行调整
  3. 状态修正: 考虑瞄准、蹲伏、移动等状态对属性的影响
  4. 小数处理: 计算结果建议保留一位小数后四舍五入取整

# Python自动计算程序

警告

自动计算不适用于所有枪械!出现问题数据请手工计算!

Python自动计算程序
python
import os
import yaml
import json
from pathlib import Path

def find_yml_files(root_dir):
    """查找指定目录下所有yml文件(支持嵌套文件夹)"""
    yml_files = []
    for root, dirs, files in os.walk(root_dir):
        for file in files:
            if file.endswith('.yml') or file.endswith('.yaml'):
                yml_files.append(os.path.join(root, file))
    return yml_files

def extract_value_by_path(data, path):
    """根据路径提取值,支持嵌套结构"""
    keys = path.split('.')
    current = data
    
    try:
        for key in keys:
            if isinstance(current, dict) and key in current:
                current = current[key]
            else:
                return None
        return current
    except (KeyError, TypeError):
        return None

def calculate_firepower(weapon_data):
    """计算火力输出能力 Firepower = (Base_Damage × Shots_Per_Second) × (1 - 平均伤害衰减比例)"""
    base_damage = extract_value_by_path(weapon_data, 'Damage.Base_Damage')
    shots_per_second = extract_value_by_path(weapon_data, 'Shoot.Fully_Automatic_Shots_Per_Second')
    
    if base_damage is None or shots_per_second is None:
        return 0
    
    # 计算平均伤害衰减比例
    dropoff = extract_value_by_path(weapon_data, 'Damage.Dropoff')
    avg_dropoff = 0
    if dropoff and isinstance(dropoff, list):
        total_drop_rate = 0
        valid_entries = 0
        for item in dropoff:
            if isinstance(item, str):
                parts = item.strip().split()
                if len(parts) == 2:
                    try:
                        distance = float(parts[0])
                        damage_reduction = float(parts[1])
                        if base_damage != 0:
                            drop_rate = abs(damage_reduction) / base_damage
                            total_drop_rate += drop_rate
                            valid_entries += 1
                    except ValueError:
                        continue
        if valid_entries > 0:
            avg_dropoff = total_drop_rate / valid_entries
    
    firepower = (base_damage * shots_per_second) * (1 - avg_dropoff)
    return max(0, min(100, firepower))

def calculate_accuracy(weapon_data):
    """计算精度 Accuracy = MAX(0, 100 - (Base_Spread × 15))"""
    base_spread = extract_value_by_path(weapon_data, 'Shoot.Spread.Base_Spread')
    
    if base_spread is None:
        return 0
    
    accuracy = 100 - (base_spread * 15)
    return max(0, min(100, accuracy))

def calculate_stability(weapon_data):
    """计算稳定性 Stability = 100 - (Recoil_Accumulation × 10 + Recoil_Speed × 5)"""
    max_accumulation = extract_value_by_path(weapon_data, 'Shoot.Recoil.Max_Accumulation')
    recoil_speed = extract_value_by_path(weapon_data, 'Shoot.Recoil.Speed')
    
    if max_accumulation is None or recoil_speed is None:
        return 0
    
    stability = 100 - (max_accumulation * 10 + recoil_speed * 5)
    return max(0, min(100, stability))

def calculate_mobility(weapon_data):
    """计算机动性 Mobility = MAX(0, 50 + (movement_speed_modifier × 1000))"""
    attributes = extract_value_by_path(weapon_data, 'Info.Weapon_Item.Attributes')
    
    movement_speed_modifier = 0
    if attributes and isinstance(attributes, list):
        for attr in attributes:
            if isinstance(attr, str) and 'movement_speed' in attr:
                try:
                    parts = attr.split()
                    if len(parts) >= 2:
                        movement_speed_modifier = float(parts[1])
                        break
                except ValueError:
                    pass
    
    mobility = 50 + (movement_speed_modifier * 1000)
    return max(0, min(50, mobility))

def calculate_effective_range(weapon_data):
    """计算有效射程:当伤害降到Base_Damage的50%时的距离"""
    base_damage = extract_value_by_path(weapon_data, 'Damage.Base_Damage')
    dropoff = extract_value_by_path(weapon_data, 'Damage.Dropoff')
    
    if base_damage is None or base_damage <= 0:
        return 50  # 默认值
    
    target_damage = base_damage * 0.5  # 50%基础伤害
    
    if not dropoff or not isinstance(dropoff, list):
        return 50  # 默认值
    
    # 解析伤害衰减数据
    damage_points = []
    for item in dropoff:
        if isinstance(item, str):
            parts = item.strip().split()
            if len(parts) == 2:
                try:
                    distance = float(parts[0])
                    damage_reduction = float(parts[1])
                    actual_damage = base_damage + damage_reduction  # damage_reduction是负值
                    damage_points.append((distance, actual_damage))
                except ValueError:
                    continue
    
    # 按距离排序
    damage_points.sort(key=lambda x: x[0])
    
    # 如果没有衰减数据点,返回默认值
    if len(damage_points) == 0:
        return 50
    
    # 如果第一个点就已经低于50%伤害,返回第一个点的距离
    if damage_points[0][1] <= target_damage:
        return max(0, min(100, damage_points[0][0]))
    
    # 查找目标伤害所在的区间
    for i in range(len(damage_points) - 1):
        distance1, damage1 = damage_points[i]
        distance2, damage2 = damage_points[i + 1]
        
        # 如果目标伤害在这个区间内
        if damage2 <= target_damage <= damage1:
            # 线性插值计算精确距离
            if damage1 != damage2:
                ratio = (target_damage - damage2) / (damage1 - damage2)
                effective_distance = distance2 + ratio * (distance1 - distance2)
                return max(0, min(100, effective_distance))
            else:
                return max(0, min(100, distance1))
    
    # 如果所有点都高于50%伤害,返回最远点的距离
    return max(0, min(100, damage_points[-1][0]))

def process_weapon_file(file_path):
    """处理单个武器文件"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            file_data = yaml.safe_load(f)
        
        if not file_data or not isinstance(file_data, dict):
            return None
        
        # 获取武器根键名(如 "Uzi")
        weapon_root_key = list(file_data.keys())[0] if len(file_data.keys()) > 0 else None
        if not weapon_root_key:
            return None
        
        weapon_data = file_data[weapon_root_key]
        weapon_name = extract_value_by_path(weapon_data, 'Info.Weapon_Item.Name') or weapon_root_key
        
        # 计算六大属性
        firepower = calculate_firepower(weapon_data)
        accuracy = calculate_accuracy(weapon_data)
        stability = calculate_stability(weapon_data)
        mobility = calculate_mobility(weapon_data)
        reload_speed = calculate_reload_speed(weapon_data)
        effective_range = calculate_effective_range(weapon_data)
        
        return {
            'weapon_name': weapon_name,
            'weapon_key': weapon_root_key,
            'file_path': file_path,
            'attributes': {
                'firepower': round(firepower, 1),
                'accuracy': round(accuracy, 1),
                'stability': round(stability, 1),
                'mobility': round(mobility, 1),
                'reload_speed': round(reload_speed, 1),
                'effective_range': round(effective_range, 1)
            }
        }
    except Exception as e:
        print(f"处理文件 {file_path} 时出错: {str(e)}")
        return None

def calculate_reload_speed(weapon_data):
    """计算换弹效率 Reload_Speed = MAX(0, 50 - Reload_Duration / 2)"""
    reload_duration = extract_value_by_path(weapon_data, 'Reload.Reload_Duration')
    
    if reload_duration is None:
        return 0
    
    reload_speed = 50 - (reload_duration / 2)
    return max(0, min(50, reload_speed))

def main():
    """主函数"""
    # 创建wp目录(如果不存在)
    wp_dir = './wp'
    if not os.path.exists(wp_dir):
        print(f"目录 {wp_dir} 不存在")
        return
    
    # 查找所有yml文件
    yml_files = find_yml_files(wp_dir)
    
    if not yml_files:
        print("未找到任何yml文件")
        return
    
    print(f"找到 {len(yml_files)} 个yml文件")
    
    # 处理所有武器文件
    weapons_data = []
    for file_path in yml_files:
        print(f"处理文件: {os.path.basename(file_path)}")
        weapon_info = process_weapon_file(file_path)
        if weapon_info:
            weapons_data.append(weapon_info)
            print(f"  武器: {weapon_info['weapon_name']}")
            print(f"  属性: {weapon_info['attributes']}")
    
    # 输出为JSON
    output_data = {
        'total_weapons': len(weapons_data),
        'weapons': weapons_data
    }
    
    # 保存到文件
    output_file = 'weapons_attributes.json'
    with open(output_file, 'w', encoding='utf-8') as f:
        json.dump(output_data, f, ensure_ascii=False, indent=2)
    
    print(f"\n处理完成,结果已保存到 {output_file}")
    
    # 同时打印到控制台
    print("\nJSON输出:")
    print(json.dumps(output_data, ensure_ascii=False, indent=2))

if __name__ == '__main__':
    main()