雨中冒险2Proc系数及机制详解 触发流内核剖析

时间:2022-11-19 06:27

雨中冒险2触发流是游戏中的一个经典流派,游戏中各种类型的装备如何触发?下面一起来看看雨中冒险2Proc系数及机制详解

雨中冒险2Proc系数及机制详解

首先,雨中冒险2(下称ROR2)的伤害机制是这样的。

玩家使用技能 Skill,通过 投射物/球体/其他方式 造成了各种类型的伤害,代码里赋予一个 DamageInfo 的 类 用于记录本次技能造成的伤害。

DamageInfo 经过 GlobalEventMangaer 类的 OnHitEnemy 事件,判断技能击中敌人后产生的各种效果,判断各种物品的触发。判断完毕后,开始计算伤害-------进入 HealthComponent 类 的 TakeDamage 事件,从而计算最终伤害。

而我们今天这篇文章的重点,将注重于 OnHitEnemy 这个事件里,使用 Proc Coefficient 触发系数 进行计算触发型道具的原理。

任何角色造成的伤害都属于 DamageInfo 类。而这个类里有一个 float 属性 是 procCoefficient。

这个属性影响了我们的各类击中后触发的效果以及伤害。

我们拿我们最熟悉的光头 Commando 来举例

雨中冒险2Proc系数及机制详解 触发流内核剖析

Double Tap 双击 技能 拥有1 proc系数,同时造成100%的伤害。

那么在你拥有5个粘性炸弹,1个 MK1 导弹的时候。

一次技能 有 (5x5)x 1 =25% 的概率触发 粘性炸弹,造成100% x 180%=180%的合计伤害。

一次技能 有 (10%)x 1 =10% 的概率触发 一个导弹,造成100% x 300%=300%的合计伤害。

以光头作为模板,我们来看看其他拥有不同的伤害和proc系数的技能是怎么样的。

雨中冒险2Proc系数及机制详解 触发流内核剖析

Auto-Nailgun 自动钉枪 技能 拥有 0.6 proc系数,同时造成70%的伤害。

那么在你拥有5个粘性炸弹,1个 MK1 导弹的时候。

一发钉子 有 (5x5)x 0.6 =15% 的概率触发 粘性炸弹,造成70% x 180%=126% 的合计伤害。

一发钉子 有 (10%)x 0.6 =6% 的概率触发 一个导弹,造成70% x 300%=210% 的合计伤害。

发现了吗?对于输出频率高的小车,作者 hopoo 选择了引入 proc系数 这一机制来平衡 高攻击频率和其他技能的触发平衡。

In Hopoo Games Development Thoughts #1, the developers introduced the concept of proc coefficient like so:

"MUL-T’s nailgun has a low proc coefficient per nail of 0.4 compared to most character’s 1.0, so he isn’t proccing stuff a ton faster than other characters." - Quote from NaKyle, 03/30-2019.

在 Hopoo Games 的游戏设计思想讨论#1 里,开发者对Proc系数的描述是这样的:

"MUL-T的钉枪,每根钉子的proc系数很低,只有0.4,而大多数角色都是1.0,所以他触发道具的速度并不比其他角色快上一大堆。" - 引自NaKyle,2019年03月30日。

(备注,之后小车的proc系数从0.4改成了0.6,重振颓势,复兴小车荣耀 我辈义不容辞)

作者引入Proc 系数这一概念,有效地将攻击频率快,但是伤害低的技能 和 攻击频率慢,但是伤害高的技能 ,在触发道具的数值上作出了合理的平衡。

那么。如果一次伤害, DamegeInfo 的proc系数是0的情况呢?

雨中冒险2Proc系数及机制详解 触发流内核剖析

如果一次伤害的proc系数为0,那么接下来所有触发内容都不会被响应。

相信细心的读者可能已经联想到了,有时候你的导弹/火球 会触发尤克里里,冰环火环等装备。

要知道,触发的特效造成的伤害,也是会进入OnHitEnemy这一事件响应中的。而触发道具的伤害都含有自己的proc系数。

那么为什么我们不会看见导弹 触发 尤克里里,尤克里里再触发导弹的死循环?

这里就要引入一个新的概念,叫做 procChainMask 我称之为 Proc连锁机制。

在OnhitEnemy事件中,计算完各类保证伤害正常的代码,保证Proc系数不为0的情况之下,我们造成的伤害会经过第一层判断。

if (damageInfo.crit){GlobalEventManager.instance.OnCrit(component, master, damageInfo.procCoefficient, damageInfo.procChainMask);}

如果角色的crit暴击率大于100,那么这次伤害会直接判断并标记为为暴击,接下来在TakeDamage事件里使得最终伤害翻倍。

Proc系数不影响暴击,暴击独立于Proc系统。

if (!damageInfo.procChainMask.HasProc(ProcType.Missile)){this.ProcMissile(inventory.GetItemCount(RoR2Content.Items.Missile), component, master, teamIndex, damageInfo.procChainMask, victim, damageInfo);}

而接下来,就是判断是否触发各类道具的时刻了。

我们可以看到,如果这次伤害,也就是 damageinfo 的 procChainMask 属性 不具有 导弹的 ProcType 触发种类,那么就会进入触发导弹的判断。

if (Util.CheckRoll(10f * damageInfo.procCoefficient, attackerMaster)){float damageCoefficient = 3f * (float)stack;float damage = Util.OnHitProcDamage(damageInfo.damage, attackerBody.damage, damageCoefficient);ProcChainMask procChainMask2 = procChainMask;procChainMask2.AddProc(ProcType.Missile);FireProjectileInfo fireProjectileInfo = new FireProjectileInfo{projectilePrefab = this.missilePrefab,position = position,rotation = Util.QuaternionSafeLookRotation(up),procChainMask = procChainMask2,target = victim,owner = gameObject,damage = damage,crit = damageInfo.crit,force = 200f,damageColorIndex = DamageColorIndex.Item};ProjectileManager.instance.FireProjectile(fireProjectileInfo);}

首先会通过随机数判断是否触发导弹,而这个随机数的概率判断会经过proc系数的一次修正。

所以小车触发导弹的几率会是10f x 0.6 = 6%。

然后计算堆叠数,判断出这次Projectile 投射物的 基础伤害。

如果成功触发导弹,则会发射出一个导弹(废话)

而这个导弹被一个语句赋予了一个属性。

procChainMask2.AddProc(ProcType.Missile);

这个导弹之后造成的伤害,也就是属于这个导弹的damageinfo ,会被打上一个导弹的ProcType。

就像是你对一个人施放了魔咒,刻下了一个印记,那么这个印记就不会再被别人重复刻上。

然后回头看看之前的触发语句。

if (!damageInfo.procChainMask.HasProc(ProcType.Missile))

如果这次伤害 Damageinfo 里不具有 ProcType.Missile 导弹属性。那么才会进入判断导弹的触发。

也就是说,这解决了一个问题,导弹是不会重复触发导弹的。

那么导弹触发的尤克里里,会不会再触发导弹?

答案是不会。

为什么?

因为ProcChainMask 是继承的,犹如链条一般。

发射出去的导弹具有 ProcType.Missile 的属性,而如果这个导弹触发了别的道具,那么别的道具造成的伤害 Damageinfo 里,也会有这个属性。

也就是说,导弹触发的尤克里里,造成的闪电弹射伤害,已经被导弹玷污了(雾),再也没法触发导弹了。

同理,导弹触发的熔岩钻机,迸射出的火球也不能再触发导弹。

这就是 Proc 连锁机制,保证游戏伤害平衡而不卡死的关键。

了解了以上内容,我们就可以对症下药,更合理地构建自己的build了。

附录1

Q:为什么我拿了很多撬棍和水晶,还是没法触发火环?

if (damageInfo.damage / component.damage >= 4f && component.HasBuff(RoR2Content.Buffs.ElementalRingsReady))

首先必须你造成的伤害 DamageInfo,具有不为 0 的 proc系数。

其次必须你造成的总计伤害数值,是你 面板伤害 的 400%。

而撬棍和水晶的伤害加成,并不是计算在DamageInfo 里面的,而是通过TakeDamage事件里的最终伤害加成实现的。也就是提高终伤并不能触碰到冰火环的阈值。

int itemCount2 = master.inventory.GetItemCount(RoR2Content.Items.NearbyDamageBonus);if (itemCount2 > 0 && vector.sqrMagnitude <= 169f){damageInfo.damageColorIndex = DamageColorIndex.Nearby;num *= 1f + (float)itemCount2 * 0.2f;......

上为凝神水晶的代码,可以看到只是提高终伤数值 num. 而不是修改damageinfo的damage属性.

if (damageInfo.crit){num *= 2f;}

同时这里有一个很简单粗暴的暴击双倍伤害代码,也是放在TakeDamage事件里的。

所以如果想触发冰火环,你需要让技能的伤害x道具的伤害 超过400%。

比如如果你是光头,想用平A M1 触发 火环,那你需要2个导弹,发射一发导弹造成600%的伤害,才能触发。

如果你是铁拳Loader,平A只有340%,那么你如果触发1个导弹,就是1020%的伤害,绝对能触发火环。

附录2

常见物品的Proc系数和影响范围 (T1 T2 T3 TB TE为 白绿红黄装 )

影响范围

T1 三尖匕首:影响 触发几率 和 持续时间

T1 眩晕手雷:触发几率

T1 黏弹:触发几率

T2 AtG导弹MK.1:触发几率

T2 尤克里里:触发几率

T2 吸血种子:回复量

T2 捕食本能:攻速Buff 持续时间

T2 收割者镰刀:回复量

T3 完美巨兽:爆炸半径

T3 感应肉钩:触发几率

*T3 秃鹫苏醒

火焰精英(伊芙利特的卓越):燃烧 持续时间

冰霜精英(她的噬咬拥抱):减速 持续时间

天青石精英(幽灵头饰):减速 持续时间

孔雀石精英(恩库哈呐的反驳):禁疗Buff 持续时间

T3 粉碎的正义:减甲 持续时间

TB 熔融钻机:触发几率

TB 电能钻机:触发几率

Proc系数

非列出的幸存者技能均为1。

Acrid 绝命毒师 shift 腐蚀跳跃 酸池持续伤害 0.1

Artificer 工匠 M2 充能完毕的纳米炸弹 能量卷须 0.3

Bandit 盗贼 M1 迸射 每个弹丸0.5. (5个弹丸)

Captain 船长 M1 火神霰弹枪 每个弹丸0.75(8个弹丸)

Captain 船长 R 轨道补给信标 0 (?)

Commando M2 突击队员(指挥官) 相位爆破 0.5 (8个弹丸)

Engineer 工程师 R TR58碳化器炮塔 平A 0.6 (移动炮台)

Huntress 女猎手 M1 疾风 0.7 (3下)

Loader 装弹手 R M551电塔 0.5

MUL-T 多面手 M1 自动钉枪 0.6(12个钉子)

MUL-T 多面手 M2 爆破筒 0.3(子母弹)

Rex 雷克斯 M1 命令:注射 0.5 (3下)

Rex 雷克斯 M2 命令:钻孔 0.5

Rex 雷克斯 shift 树莓齐射 0.5

Rex 雷克斯 R 触须生长 0(持续伤害)

物品,非列出的均为1。

T1 一捆烟花 0.2

T1 黏弹 0

T1 汽油 0 (和鬼火不同机制!)

T2 鲁纳德的手环 0

T2 贾罗的手环 0

T2 剃刀尖网 0.5

T2 尤克里里 0.2

T2 鬼火 1 (wiki写的1,目前没研究出来能不能触发,代码里看不太明白)

T3 完美巨兽 0

T3 仪式匕首 1

T3 冰霜圣物 0.2

T3 恩库哈呐的意见 0.2

T3 共鸣圆盘 穿刺 1 爆炸 0

T3 感应肉钩 0.33

T3 不稳定的特斯拉线圈 0.3

TE 前子蓄能器 触须 0.1

TL 异端幻象 爆炸伤害1,触碰伤害0.1

标签:
随便看看
本类推荐
本类排行
热门标签

我国国家通讯社行不行啊细狗新年贺词祝福语2023年祝福语新年新年贺词新年贺词祝福语居家抗病毒小药箱除夕高速免费吗2022年除夕高速免费吗春联春联句子大全春联句子大全七字年夜饭十二道菜年夜饭十二道菜单年夜饭吃什么年夜饭吃什么菜吃年夜饭的寓意年夜饭黑芝麻菊花茶晒菊花茶腌腊肉送妈妈生日礼物汉白玉送闺蜜水钻送女人礼物爸爸生日送礼物送老公