A simple python script to generate damage curve for game Arknights
一个简单的python代码,用于生成300秒内各个干员的期望伤害的时间曲线
同时发布于NGA帖子,欢迎捧场
数据和影像资源全部来自于游戏本体,如遇版权问题,可能随时删除(我猜这玩意儿应该遇不上版权问题)
-
需要 Python。理论上这份代码需要 Python >= 3.6,但我只在 Python 3.7 上测试过。
-
需要 matplotlib >= 3.0
Windows, Mac 和 Linux 均可通过 pip 安装matplotlibpython -m pip install -U pip python -m pip install -U matplotlib
-
需要 思源黑体 字体
matplotlib 需要 TrueTypeFont (TTF) 文件, 但源文件没有TTF版本。所以我附带了一份我自己转换的SourceHanSansSC-Normal.ttf
由于中文字体文件比较大 (19.2MB),所以也传到了百度网盘上,不必通过Git下载:思源黑体TTF 提取码: fgy3 -
需要配置 matplotlib 来让它支持中文字体
你可以在知乎问题 https://www.zhihu.com/question/25404709 里找到 Windows 和 Mac 中的 matplotlib 的中文配置方法 -
在环境配置结束后,Clone or Download 这个文件夹至你的电脑,然后即可使用命令行或你的IDE运行python代码
- 简单用法:通过运行
main.py
来生成默认的一系列伤害曲线图python main.py
,当然你也可以在IDE里运行- 运行后会生成一系列的图片,包括了5种在高难合约里常见的干员组合面对各种敌人时的输出期望曲线
- 预设的角色组合如下:
组合 | 角色 | ||
---|---|---|---|
Melee Physical 近战物理干员 | 煌 | 赫拉格 | 陈 |
银灰 (3) | |||
Melee Magic 近战法术干员 | 陈 (2) | 布洛卡 (2) | 星极 |
拉普兰德 (2) | 慕斯 | ||
Ranged Physical 高台物理干员 | 黑 (2,3) | 能天使 (2,3) | 送葬人 |
陨星 | 蓝毒 | ||
Ranged Magic 高台法术干员 | 安洁莉娜 | 艾雅法拉 | 伊芙利特 |
Control 控制队干员 | 安洁莉娜 (2,3) | 莫斯提马 (2) | 格劳克斯 (2) |
食铁兽 | 狮蝎 (1) | 伊桑 (2) |
-
进阶用法:通过运行
plot.py
来生成你自己想要的伤害曲线图,但你需要进行一些参数的设置- 修改
plot.py
中的参数,主要在__main__
函数部分。你可以参考plot.py
中的一些预设的参数 - 在
plot.plot(...)
你可以看到更多的关于参数的注释
- 修改
-
过一段时间会增加更多的介绍,包括假想敌的设置、更具体的用法、参数介绍、例子说明等
在做了咕咕咕咕咕咕
-
main.py
中参数和plot.py
中基本一致,下面仅介绍plot.py
的参数 -
plot.py / Stage
目前支持 "29010", "25010", "2307" 三个参数
会自动读取对应练度的干员数据,并以此计算伤害曲线
"29010" 时,高于等级上限的数据会自动修正为满级数据
plot.py / SimulateTime
设置模拟伤害曲线的总时长,单位为秒
默认为300秒,修改后会有轻微错位,修改的值过大或过小的话可能会有部分图像遮挡
plot.py / Pick
设置后,会读取
DefaultPickList
内的对应数据(1)
plot.py / PickList
作图时,只会显示
PickList
内的干员的输出曲线(2)
plot.py / PickListName
文件名会标注
PickListName
(3)
plot.py / Baseline
作图时,会以
Baseline
对应的干员的总伤害为100%
其他干员的数据会进一步换算为该数据的百分比,以便读数
plot.py / Enemy
支持
character.py / enemy_dict
内的内容
会读取对应敌人的数据,并按照该敌人的 生命,防御,法抗 来计算干员的输出
会自动安装敌人生命计算敌人数目,使得多个敌人的总生命大约在到 80,000 ~ 150,000 之间
敌人数据会显示出来,若想自己增添新的敌人,可以参考character.py / enemy_dict
的格式,并在 图片 中展示出来
plot.py / ShowSlayLine
若为
True
,则会显示斩杀线和斩杀时间
若为False
,则不会显示斩杀线和斩杀时间,图片更干净
在下方的 斩杀线示例图片 中可以看到 “斩杀线和斩杀时间” 是什么
plot.py / MultiTarget
若为
True
,则会按照character.py / target_num_dict
中填写的攻击目标数来计算总伤害
若为False
,则会计算只打1个目标的伤害,避免争议
在 总伤害图例右侧,即图片的最右端,会同时显示攻击的目标数量 在 附录 里有 所有攻击范围对应的攻击目标数 的表格,仅供参考
想要自定义攻击目标数的同志们可以好好考虑一下,填写攻击目标数是一个困难的任务,我的数据也有许多不合理之处,如果有老哥能提供更合理的假设那就再好不过了
plot.py / IgnorePolish
若为
True
,则会按照一个公式计算抛光线,输出低于抛光线的干员的图例将不显示
若为False
,则不会设置抛光线,所有干员的图例都会显示出来
抛光线计算公式在plot.py / plot_legend
中的polish_line = ...
部分
默认公式为:$\text{polish_line} = \sqrt{\frac{\text{max_damage}}{10,000}} \times 10,000$
在下方的 抛光线示例图片 中可以看到 “斩杀线和斩杀时间” 是什么
这是为了防止在面对特殊敌人时抛光干员太多,导致图例集中在图片下部过于集中,影响阅读
plot.py / DefaultPickList
这是一个词典 (Dict),你可以任意选择或增删内部的词条,从而能够生成不同的干员组合的输出曲线
character.py / Charge_on_defense_equivalent_charge_speed
character.py / Hellagur_talent_hp_ratio
character.py / Provence_Wolfeye_target_hp_ratio
三个参数分别对应:
受击回复干员等效的每秒回复sp量
赫拉格的生命比例(以此计算攻击速度)
普罗旺斯-狼眼的敌人生命比例(以此计算伤害)
character.py / color_dict
可以自定义干员的输出曲线的颜色,如果你看不清曲线,可以调整曲线颜色
默认的曲线颜色参考了干员精二立绘里,干员的替身的颜色
注:这俩图片可能需要一段时间才能加载出来
-
Requires Python. In theory this code can be run on Python >= 3.6, but I only test this code in Python 3.7
-
Requires matplotlib >= 3.0.
Both Windows, Mac and Linux can install matplotlib from pippython -m pip install -U pip python -m pip install -U matplotlib
-
Requires Font 思源黑体.
matplotlib requires TrueTypeFont file, but the source file is not provided in TTF version. So I provide a converted versionSourceHanSansSC-Normal.ttf
in the repo. -
You also need to configure your matplotlib to make it support Chinese font.
You may check https://www.zhihu.com/question/25404709, where both Mac and Windows can find instructions for setting Chinese font.
- Simple usage: To generate default damage curve images, run:
python main.py
, or run the code in your IDE- It will automatically generate a series of images, containing the damage curves for some most commonly used characters.
- Default characters are listed below:
Group | Characters | ||
---|---|---|---|
Melee Physical | Blaze | Hellagur | Ch'en |
Silver Ash (3) | |||
Melee Magic | Ch'en (2) | Broca (2) | Astesia |
Lappland (2) | Mousse | ||
Ranged Physical | Schwarz (2,3) | Exusiai (2,3) | Executor |
Meteorite | Blue Poisson | ||
Ranged Magic | Angelina | Eyjafjalla | Ifrit |
Control | Angelina (2,3) | Mostima (2) | Glaucus (2) |
FEater | Manticore (1) | Ethan (2) |
-
More usages: To generate customized damage curve, you need to:
- Change parameters in
plot.py
. There are some preset parameters inplot.py
- You can see more description of those parameters in the comment of
plot.plot(...)
- Change parameters in
-
More descriptions will be added in the future
文本描述 | 范围代号 | 干员 | 攻击范围 对应干员 | 打2 | 打3 | 打4 | 打5 | 打6 | 打7 | 群攻 |
---|---|---|---|---|---|---|---|---|---|---|
0格 | 0-1 | 火神 (2) 格拉尼 (2) 坚雷 (2) 麦哲伦 (2) - 技能 |
1.3 | 1.87 | 2.2 | 2.31 | 2.35 | 2.38 | 2.4 | |
1格 | 1-1 | 群卫 星极 (2) 星熊 (2) 煌 (3) - 切割 |
1.4 | 2 | 2.4 | 2.57 | 2.63 | 2.67 | 2.7 | |
2格 | 2-2 | 煌 (2) 雷蛇 (2) 赫拉格 (3, 1~7级) |
1.5 | 2.12 | 2.52 | 2.7 | 2.85 | 2.9 | 2.95 | |
3格 | 3-2 | 暴行 (2) 布洛卡 (2) 赫拉格 (3, 8~10级) |
1.55 | 2.21 | 2.61 | 2.82 | 3.02 | 3.08 | 3.15 | |
4格 | 4-1 | 暗索 (2) | 1.6 | 2.28 | 2.71 | 2.93 | 3.14 | 3.21 | 3.3 | |
5格 | 5-1 | 伊芙利特 | 1.65 | 2.35 | 2.8 | 3.03 | 3.2 | 3.3 | 3.4 | |
2格远卫 | 2-3 | 精零 远卫 精零 群法 精零 近狙 |
1.6 | 2.3 | 2.75 | 2.97 | 3.19 | 3.28 | 3.35 | |
3格远卫 | 3-12 | 拉普兰德 (2) 陈 (2) |
1.65 | 2.35 | 2.83 | 3.07 | 3.25 | 3.35 | 3.45 | |
1格扇形 | 1-2 | 银灰 (2) | 1.5 | 2.12 | 2.54 | 2.74 | 2.87 | 2.94 | 3 | |
2格扇形 | 2-1 | 暂无 | 1.65 | 2.37 | 2.83 | 3.07 | 3.24 | 3.35 | 3.45 | |
2+1格扇形 | 3-11 | 暂无 | 1.67 | 2.4 | 2.86 | 3.1 | 3.27 | 3.38 | 3.48 | |
3格扇形 | 3-7 | 银灰 (3) | 1.75 | 2.5 | 2.95 | 3.25 | 3.52 | 3.7 | 3.85 | |
1格菱形 | x-5 | 推进之王 (2) | 1.55 | 2.15 | 2.58 | 2.78 | 2.95 | 3.03 | 3.1 | |
2格菱形 | x-1 | 德克萨斯 (2) | 1.7 | 2.42 | 2.9 | 3.15 | 3.35 | 3.46 | 3.55 | |
药物配置 | x-2 | 真理 (2) | 1.78 | 2.53 | 3.04 | 3.38 | 3.65 | 3.81 | 3.95 | |
3格菱形 | x-3 | 艾雅法拉 (3) 格劳克斯 (2) |
1.8 | 2.55 | 3.05 | 3.4 | 3.75 | 3.98 | 4.15 | |
1格方形 | x-4 | 精零 空 | 1.62 | 2.32 | 2.76 | 3 | 3.2 | 3.28 | 3.35 | |
精一群法 | 3-6 | 莫斯提马 (2) 煌 (3) - 爆裂 |
1.65 | 2.38 | 2.87 | 3.13 | 3.3 | 3.42 | 3.52 | |
精零快狙 | 3-1 | 蓝毒 (1) | 1.68 | 2.42 | 2.92 | 3.17 | 3.34 | 3.46 | 3.56 | |
精一快狙 | 3-3 | 蓝毒 (1, 2) 红云 (2) 流星 (2) 远山 (2) |
1.7 | 2.44 | 2.92 | 3.2 | 3.4 | 3.52 | 3.62 | |
精一群狙 | 3-8 | 精一 群狙 | 1.72 | 2.46 | 2.94 | 3.22 | 3.43 | 3.55 | 3.65 | |
精二群狙 | 3-10 | 精二 群狙 | 1.74 | 2.48 | 2.96 | 3.25 | 3.46 | 3.58 | 3.7 | |
精零敌飚 | 5-2 | 暂无 | 1.76 | 2.5 | 2.98 | 3.28 | 3.5 | 3.63 | 3.75 | |
精零群奶 | y-1 | 狮蝎 伊桑 |
1.65 | 2.37 | 2.83 | 3.07 | 3.24 | 3.35 | 3.45 | |
精一群奶 | y-2 | 精零 初雪 (1) 格劳克斯 (1) |
1.68 | 2.42 | 2.92 | 3.17 | 3.34 | 3.45 | 3.55 | |
黑夜视觉 | y-3 | (二测) 精二 白面鸮 | 1.7 | 2.43 | 2.91 | 3.18 | 3.38 | 3.5 | 3.6 | |
脑啡肽 | y-7 | 白面鸮 (2) | 1.72 | 2.44 | 2.93 | 3.21 | 3.42 | 3.54 | 3.65 | |
黑夜脑啡肽 | y-5 | (二测) 精二 白面鸮 (2) | 1.73 | 2.45 | 2.94 | 3.22 | 3.44 | 3.56 | 3.67 | |
精一初雪 | y-6 | 初雪 | 1.74 | 2.48 | 2.99 | 3.29 | 3.53 | 3.67 | 3.8 | |
反重力 | y-4 | 安洁莉娜 (3) | 1.77 | 2.53 | 3.05 | 3.36 | 3.62 | 3.78 | 3.92 | |
4格霰弹 | 2-4 | 精零 送葬人 | 1.57 | 2.24 | 2.66 | 2.87 | 3.06 | 3.14 | 3.22 | |
6格霰弹 | 2-5 | 精一 送葬人 | 1.62 | 2.33 | 2.77 | 3.01 | 3.22 | 3.3 | 3.37 | |
7格霰弹 | 3-13 | (二测) 精零 艾雅法拉 | 1.63 | 2.34 | 2.79 | 3.04 | 3.26 | 3.35 | 3.43 | |
9格霰弹 | 3-14 | 崖心 (2) | 1.67 | 2.38 | 2.83 | 3.09 | 3.31 | 3.41 | 3.5 | |
10格霰弹 | 4-2 | (二测) 精一 艾雅法拉 | 1.69 | 2.4 | 2.85 | 3.12 | 3.34 | 3.44 | 3.53 | |
序时之匙 | 3-4 | 莫斯提马 (3) | 1.75 | 2.51 | 3.03 | 3.35 | 3.6 | 3.76 | 3.9 | |
精一远狙 | 3-9 | 精一 守林人 | 1.77 | 2.53 | 3.05 | 3.36 | 3.62 | 3.78 | 3.92 | |
13格 | 3-5 | 暂无 | 1.67 | 2.41 | 2.88 | 3.17 | 3.4 | 3.53 | 3.65 | |
唱沙 | 唱沙 | 暂无 |
溅射型群攻 圆溅射 | 超小半径 | 小半径 | 中半径 | 大半径 | 超大半径 |
预设攻击目标数 | 1.2 | 1.9 | 2.6 | 3.2 | 3.6 |
干员列表 | 麦哲伦 (3) 常态无人机 | 白雪 (2) | 普通群狙 | 空爆 (1) | 陨星 (1) |
陨星 (2) | 普通群法 | 天火 (2) | |||
艾雅法拉 (2) | |||||
特殊干员 | 守林人 (2) 战术电台 2发 | 4.2 | 守林人 (2) 战术电台 3发 | 5.5 |
懒得自己写了,GitHub的README又不支持CSS,干脆借Mooncell的一用
来源:Mooncell-攻击范围一览
- 黑的机制较为复杂,目前采用模拟法实现计算
黑所能造成的伤害分为6种,分别为:
平A,无破甲,不触发天赋
平A,有破甲,不触发天赋
平A,触发天赋(此时必然破甲)
技能,同样有上述三种类型这个过程十分复杂,而且由于有技能和非技能两种状态,它是个非遍历的随机过程,即无法通过一次模拟得出各种攻击所占的比例。因为每个技能都有初始sp,而且初始状态不同,攻击次数相当大,想要算出解析解相当麻烦
来举一个直观的例子:精二黑,专三1技能
平A(第一下, 0s):20%天赋,80%不破甲
平A(第二下, 1.6s):20%天赋,16%破甲,64%不破甲
平A(第三下, 3.2s):20%天赋,28.8%破甲,51.2%不破甲
技能(第四下, 4.8s):80%天赋,11.808%破甲,8.192%不破甲
平A(第五下,6.4s,现在第一下的效果过期了):20%天赋,69.76%破甲,10.24%不破甲这样虽然人类计算起来还行,但计算机上不容易写出一个通用的表达式
现在想一想1、2、3技能在不同的等级下有不同的初始sp、sp消耗,属实不容易写出一个好的算法
模拟法即通过多次重复,取随机数,最后计算多次模拟中各类攻击类型的占比,并最后求出伤害的期望数据
黑的默认模拟次数为1,000次。下面是修改模拟次数的地方:
character.py /
class Schwarz /
def simulate(...) /
第二行 simulation_times=1000
在模拟完成后,技能的比例数据会被保存到data/Schwarz_tmp_...
内,下一次用到相同的数据(相同技能和技能等级、相同时长、相同模拟次数)时,会读取保存的内容
舟游的人物属性的tag是不太便于自动读取的,比如 atk
这一个tag,一般对应 攻击力 +...%
这一次词条
但红豆、陨星这些 攻击时,...%几率当次攻击的攻击力 +...%
的tag也是 atk
,虽然它也有一个 prob
的tag,但 prob
这个tag也用于其他地方,必须手动处理才能读取正确的数据
再比如 atk_scale
这一个tag,一般对应 造成相当于攻击力...%的伤害
这一词条
但天火等干员,这个词条写成 attack@atk_scale
,并非普通的 atk_scale
再再比如 base_attack_time
这一个tag,一般对应 基础攻击间隔 +...
但天火的攻击间隔增加tag,是 base_attack_time=0.7
,对应的是 基础攻击间隔 * (1 + 0.7)
而不是 基础攻击间隔 + 0.7
而且舟游的很多干员有特殊机制,比如星极、赛雷娅就是每隔一段时间增加一些属性;狮蝎、白金就是攻击间隔影响攻击力;蓝毒、伊桑又有毒伤,蓝毒的毒伤还会受到1技能加成……
如此之多的特殊机制如果写到一个函数里,我觉得需要 if
判定的语句太多了,实在有点麻烦,又懒的写函数指针、 **kwargs
这些麻烦的语法了