边缘世界 机制研究与应用 细节篇(3)
感来源于b站视频,因为百度的问题就不发全链接了:BV1JW4y167ry
先放结论:
当小人触发顺路搬运的机制时,之前近战或开枪产生的后摇僵直会被强制取消。
而近战无前摇,开枪的前摇是瞄准时间,可以通过乱开枪特性和DLC的射击专家降低到1%。
便可在暂停的时间中无限地出剑 出拳。使小人开枪扔手榴弹的频率取决于玩家拍空格的手速。
这个BUG比较方便稳定的触发方法是:使小人附近有需要搬运的钢渣块,在远处把一个电器指派开关电源(或其他任何工作都可以),在电器或工作地点近处画上一个优先级关键的垃圾储存区。然后不停地征召取消征召小人,看到有“等待处理”就说明触发了顺路搬运。
此时小人未征召的反应调成无视,只要附近有攻击目标就可以靠疯狂按征召键来光速攻击了
以下是细节说明与效果展示:
确认你的小人没有睡觉、吃饭、神经超频之类的自动需求,如果有就靠禁用和调整管制来解决。
然后使你的小人附近有任何搬运需求,比如规划了搬运命令的钢渣块,自动需要搬运的尸体和钢铁什么的也能触发。搬运需求与小人之间的距离要在小人去工作的路程二分之一以内,可以预设很多搬运需求。

如果战场上一时没有适合的东西来搬,可以用DLC的块堆折跃来召唤块堆。

然后给小人规划一个工作,最简单的工作就是开关电器,因为一般会把开关电器的工作(即基本)优先级调成最高。去工作的路程要起码是去搬运附近东西路程的两倍以上。
记得不要让其他小人抢了工作,开关电器很容易被抢,建议要经常使用这个BUG的话还是给小人弄个专用的工作,或者暂时把其他小人征召或优先级调成无。

在电器或工作地点近处画上一个优先级关键的垃圾储存区或储存区。
注意不宜画太大,不宜画两个以上储存区,不宜有其他同类储存区优先级也是关键,否则会使AI不能稳定判断,不能触发。储存区要画在去关开关的必经之路上,而且不能离小人太近,这个距离我没测。

在暂停时不停地征召、取消征召小人,如果如下图左下角一样出现了“等待处理”,那么说明触发了顺路搬运机制,这时有攻击目标就能触发取消攻击后摇的BUG了。如果确认以上细节都做到位了还没办法顺路搬运,可以试试存新档然后直接读档,偶尔这样读档后又能触发了。


记得把未征召面对敌人的反应调成无视,然后准备好狂摁R键。

拿近战时,即使暂停时,不停按R键,即征召键即可砍倒一切接触的敌人。可以看到下图中的散弹枪子弹还没有动,已经瞬间砍死了三个敌人。
如果有DLC的话,还可以隐身往敌人身上折跃,同时还有修罗人格武器的话可以乱杀。不过还是不可能单凭这样砍死重远程火力的袭击。


但是猎杀人类这种袭击有隐身可以无脑乱杀,没有隐身的话还是会起码吃到接触到每个敌人的那一次攻击。
面对象群 两次隐身内全部驱逐


拿远程时,如果是乱开枪的射击专家小人,只需要按R键两次后,再按两下空格,即空格键就可以连续射击,就算拿的是狙击步枪,小人的射速也全看你手速。下面这张图是用按键精灵射得,手按的话子弹大概少一半。其实在打死敌人后会浪费很多枪,子弹还在飞,属实是火力压制了。

在蜈蚣从进到狙击步枪射程爬到蜈蚣炮射程内这段时间,单兵狙死了10个蜈蚣,剩余蜈蚣的血条都由于误伤掉了平均三分之二。

误操作少开了十多枪,被跟狙击步枪射速差不多的电荷冲击炮蹭到了一下,最后17只蜈蚣全歼。
破片手榴弹同理!

为纠正玩家们对虫灾生成机制的理解误区,翻了一下代码,从代码理解机制。
内容分析主要来源代码RimWorld.InfestationCellFinder与RimWorld.InfestationUtility
先放结论:
首先符合以下条件之一的地方不会成为虫灾生成的中心
①距离殖民地建筑30格以上②不可行走③在迷雾中(地图上未揭晓的区域)
④格子中有障碍物(从建筑方面判断,墙体与路障上无法生成虫灾,但电线、门与桌椅上可以)
⑤非厚岩顶⑥不存在区域⑦区域面积小于两格⑧温度低于负17℃⑨山度低于17%(山度是一种衡量附近自然岩体与厚岩顶丰富程度的参数)
对避开了以上条件的格子,有以深度为主的6个因素影响虫灾中心生成概率。
①格所在区域与露天区域之间的最短路程(深度)越长,生成概率越高,但该项上限值是直线深度值的4倍。该项是唯一可大幅提高来影响概率的重要参数。如设地图上只有A、B两格可生成虫灾,A格深度为20格,B格深度为100格,其他条件相同,则B格发生虫灾概率是A格的约20倍((5^1.55)^1.2)。
②格与露天区域之间的最短直线距离(直线深度)在0~12格范围内,以0→100%影响概率(最高100%)。如某格直线深度为3格时,该格的虫子概率降为原来的25%。
③格亮度从0~100%范围内,以100%→18%影响概率。如某格亮度为100%时,概率降为原来的18%。
④格与阻碍物之间的距离在0~6.6格范围内,以100%→40%影响概率。该项实际上使得虫灾中心贴墙生成,区域像蚂蚁窝那样多岔路、高表面积会更有利。
⑤格温度从-17℃~-7℃范围内,以0%→100%影响概率。(高温无影响,即使是室内1000℃也会照常生成)
⑥格周围半径18格内的自然岩体(无自然岩体格如果有厚岩顶算半个自然岩体)占比从0%~100%范围内,以0%→100%影响概率。自然岩体包括矿物类岩体(如压埋的机械),不包括崩落的石头和打磨过的岩体(如光滑的板岩)
空间越大,区域中产生虫灾的概率确实会越大,因为相同条件的诱虫点更多了,虽然区域中央的生成概率会因为贴墙机制变得较低。
应用可以参考https://tieba.baidu.com/p/7675881192,3楼的图。
简单来说诱虫点就是在家最深处挖一个空间,或者在一个大山体中挖一个迷宫,需要先挖一段笔直的隧道提高有效深度的上限,然后挖曲折的迷宫提高实际深度、表面积、空间大小。
终点的诱虫空间需要保证无光,不冷,空间13格宽13格长就够用了,再扩大空间不如挖得更深一点。而基地内要保持时刻处处至少有50%光。
代码分析部分:
在确定发生虫灾袭击后,系统会在RimWorld.IncidentWorker_Infestation代码运行TryExecuteWorker函数时调用SpawnTunnels函数来生成所有虫巢。
其中判断虫巢中心位置时会调用RimWorld.InfestationUtility代码中的FindRootTunnelLoc函数。
该函数又会为了决定虫巢中心的位置调用TryRandomElementByWeight函数,该函数机理放到最后再分析,意义是抽取列表中的某一项,抽取的概率根据项的权重大小而改变,项权重越大,抽取该项概率越高。在本次调用中,所有可能生成虫巢的格子组成一个列表,而每格对应的虫灾得分就是其权重。
为了计算虫灾得分,又需调用RimWorld.InfestationCellFinder代码中的GetScoreAt函数。该函数将是分析部分的重点。

GetScoreAt函数以地图和格子作为输入,将输出一个float类型的参数f,这个参数的意义就是虫灾得分。虫灾得分越高,代表虫灾中心选择生成在该格的概率越高。
在该函数的前半部分,由很多if语句组成,满足这些if条件则会使f参数直接输出0,即得分为零。这些if语句意义就是结论部分中不会成为虫灾生成中心的那些条件。

后半部分正式计算虫灾得分。
虫灾得分公式是6个参数相乘,f = value * num2 * num4 * mountainousnessScoreAt * num3 * num5。其中num2是直接深度参数,num3是亮度参数,num5是温度参数,这三个参数细节在结论部分中已经足够详细,无需赘述。
得出f后再计算它的1.2次方就是最终该格的虫灾得分,当虫灾得分小于7.5时直接清零。
Num4是阻碍物参数,这里的阻碍物与if语句中涉及到的障碍物不同,指的是不可行走的地方与地图边界。参数计算中调用DistToBlocker函数,函数意义是分别从该格四个面向出发,记下直到撞上阻碍物途中的距离,找出四个面向中最短的距离,不包括斜向。

Value是深度参数,通过TryGetValue函数间接调用CalculateTraversalDistancesToUnroofed函数,在该函数中通过Dijkstra最短路径算法来计算区域与露天区域之间的最短距离(即深度)。
间接调用成功后,临时深度参数值取深度值与直线深度值的4倍两者中较小的一方。调用失败则直接取直线深度值的1.15倍。最终深度参数值取临时深度参数值的1.55次方。
mountainousnessScoreAt 代表山度,通过调用GetMountainousnessScoreAt函数来计算,这个函数是最令人迷惑的。

其中c = cell + GenRadial.RadialPattern[i]的部分可以得到cell格周围某格c的状态,具体是哪格由i值来决定。i等于0时就是cell格,i为1~4时对应cell上下左右四个格,i为5~12时对应第二圈的8个格子,i为13~24时对应第三圈的12个格子。
不过这里i直接取0,10,20,30……直到700,相当于代码钦定的70个位置才能参与到山度计算中,不明白这么设计的特殊作用是什么,在测试中试了半天也没看出实际影响。
然后也不计入地图边界外的情况。
在山度计算过程中,设一个临时变量num,查看cell格周围钦定的70个相对位置格的状态,如果格是自然岩体,即板岩和矿物岩体那种,就使num加一。如果不是自然岩体,但屋顶是厚岩顶,也可以使num加0.5。
最后使num除以实际查看的次数,一般是除以70。这样得出的就是山度。

得到一堆格子各自的虫灾得分后,就可以由TryRandomElementByWeight函数决出最后实际的虫灾中心位置了。首先将每个list[i](即每个格)的weightSelector(即虫灾得分)累加起来,然后将总和随机乘一个值,结果落到哪个格对应的得分区间里,就是哪个格成为了真正的虫灾中心。
例如A、B、C、D四个点得分分别为10、20、20、10,总和是60,那么0~10属于A的区间,10~30属于B的区间,30~50属于C的区间,50~60属于D的区间。
通过这条函数分析可以看出,大空间因为相同条件的诱虫点更多了,区域中产生虫灾的概率会较大,哪怕空间因素不影响虫灾得分计算公式。不过超过13格长宽的区域中央的生成概率会因为贴墙机制变得较低。
最后以我另一个帖子图中基地的情况做个计算范例。
以我基地最深贴墙处与迷宫诱虫点贴墙处为例,因为都是贴着墙,所以阻碍物参数拉满达到100%。
我基地最深处离露天区域只有40格路程,而诱虫点虽然应该是有140格的深度,不过因为直线深度最多只有30格,有效深度只有120格。所以基地中的value值理论为40^1.55=304,诱虫点为120^1.55=1670。
温度没有做什么特殊处理,都为18℃左右,温度参数100%。直线深度都在12格以上,该参数也100%。使诱虫点亮度为0%,亮度参数100%,基地亮度为50%,亮度参数59%。
关于山度方面,在山里挖的基地和山里搞得迷宫实际山度都差不多,700格里除了200格厚岩顶都是自然岩体,所以山度取85%。
那么理论上我基地的某格最终的虫灾得分是(304*100%*100*85%*59%*100%)^1.2=416
诱虫点为(1670*100%*100*85%*100%*100%)^1.2=6061
诱虫点的概率是基地中概率的14倍多,也就说在诱虫点与基地厚岩顶区域空间差不多大,差不多情况的时候,有14/15的概率诱导虫灾成功。
同时考虑到空间大小、深度、亮度所做的虫灾诱导仍有1/15的失败率,只考虑空间大小和光亮失败率肯定会还要高。
不过我基地那个还是属于设计拉胯了,一般设计成功率应该会高很多。
贴个我设计诱虫空间的过程
首先建议备个测试用的档,在测试档里设计,打开开发者模式,用上帝模式来造一下,造好后查看虫灾生成概率分布,越蓝代表概率越高,基地里看不出来蓝就代表设计合理。也是为了防止挖着挖着发现别有洞天。(查看虫灾生成概率分布,先选开发者模式第三个选项open the view settings 然后选第三列第二个draw infestation chance)
第一步,找个大山体,上帝模式全挖开,看看有没有露天的洞,有的话就不太合适用来挖诱虫点。
第二步,直直挖进去一段距离,在外面也尽量向外延伸铺屋顶。这两段距离加起来乘4就是诱虫点的最大有效距离,如图最大有效距离43*4=172格
第三步,曲折的挖迷宫,拉满有效距离。如图中迷宫每行长24格,五行共120格,加上直的部分43格和诱虫空间边长12格已经拉满了。(不直接直着挖是因为地图大小有限,还要避免被别有洞天的露天区域拦截)
第四步,直接挖个12*12大小的空间用来诱虫,可以挖得更大。
最后添加一些细节。加几个火盆防止冬天时温度降到-7℃以下,让里面无光,在诱虫空间放一个人造建筑(图中是栅栏),将你的基地厚岩顶下空间挖几个直通露天区域的走廊,保证基地厚岩顶下空间常年有光。
运气好地图山体里没有莫名其妙的小洞洞,就能更进一步的挖深挖大。
各位如果在设计中发现分布概率乱七八糟,那多半也是迷宫附近有露天洞穴。



