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

2021-04-14 05:42:08单机游戏媛媛

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

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

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

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

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

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

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

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

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

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系数的技能是怎么样的。

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% 的合计伤害。

发现了吗"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的情况呢?

如果一次伤害的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

相关教程
图文教程