时间:2022-11-19 06:27
雨中冒险2触发流是游戏中的一个经典流派,游戏中各种类型的装备如何触发?下面一起来看看雨中冒险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% 的合计伤害。
发现了吗?对于输出频率高的小车,作者 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的情况呢?
如果一次伤害的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