Elin
Not enough ratings
食物效果机制(nightly23.50版)
By Kishin
食物的具体生效机制,方便大家对比料理效果,选择实际上更好的料理。写于2024.12.7
2
   
Award
Favorite
Favorited
Unfavorite
大致流程
首先,基础食物的效果倍率 = 基础100点 + 用餐区10点 + 美食家5点 + 食物品质等级*10
其中,用餐区是需要同时满足处于玩家领土且位于用餐标志范围内;美食家需要点到3,且食物需要是自己制作的才会有这+5; 食物品质等级提供的加成上限100点,也就是10级品质达到最大,在不考虑用餐区与美食家的情况下10级品质等于翻倍

(然后这个效果倍率/200,都会除所以不影响对比)

如果食物的配方里有蛋,那么上面的人肉词条无效(吃下去不会发狂,也没有人肉增益)
如果食物是祝福的,那么效果倍率*1.5
如果食物是诅咒的,那么么效果倍率*0.5

如果喜欢吃人且吃的人,那么效果倍率*1.5
如果喜欢吃人但没吃到人,效果倍率*0.5,且营养值减半
或者不喜欢吃人但是吃到了人,效果倍率*0.5

如果食用者有营养满分,那么效果倍率*1.25
如果不是玩家,那么效果倍率*3

接下来,如果吃的生食,生肉会让效果倍率*0.7,生面/生鱼会让效果倍率*0.9

然后计算营养值系数,取当前饥饿值与食物营养值的最大值,也就是营养值超过当前饥饿的部分无效
接下来如果食用者处于“饿了”以上的饥饿阶段,营养值系数*1.1(不影响营养值计算)
效果倍率会乘以上述营养值系数的十分之一

如果有厌食症,那么效果倍率固定为0.01

对于经验词条的计算:
获得的经验为 词条数值 * 营养倍率 * 词条系数
这个词条系数暂时不清楚是固定的还是有办法提高的,这里看到的默认值是 8/3,如果词条里储存了词条系数那么就不会使用这个值

对于潜力词条:
潜力词条的值/5 +1,然后随机乘以0.5~1(期望0.75)。接下来,食用者当前的临时潜力(也就是不包括基础潜力的部分)高于150时,每高出1.5点潜力,就会降低1%获得的潜力(这个说法不太准确,把超过150部分的潜力/1.5记为k,那么潜力获取会乘以 100/(100+k))

接下来,才会应用小胃和大食的饱腹度修正(也就是说这俩只影响饱腹,不影响经验获取倍率),每级小胃增加获得的饱腹度10%,每级大食减少获得的饱腹度10%
具体计算流程
吃食物的时候的具体效果在Elin.dll下FoodEffect.cs的public static void Proc(Chara c, Thing food)里,接下来按照代码里的顺序描述一下具体流程,不想看的可以直接跳过这里看下一章结论


bool flag = EClass._zone.IsPCFaction && c.IsInSpot<TraitSpotDining>();
int num = (food.isCrafted ? ((EClass.pc.Evalue(1650) >= 3) ? 5 : 0) : 0);
float num2 = (float)(100 + (flag ? 10 : 0) + num + Mathf.Min(food.QualityLv * 10, 100)) / 200f;
if (num2 < 0.1f)
num2 = 0.1f;
num2这个系数,贯穿经验计算的始终,就是我们上面说的的效果倍率,初始赋值为 基础100点 + 用餐区10点 + 美食家5点 + 食物品质等级*10 然后/200
如果小于0.1那会给你提高到0.1


然后初始化了一些值:
int num3 = food.Evalue(10);推测为营养值
float num4 = 40f;饮食评价基础值
float num5 = 1f; 饮食评价倍率
string idTaste = "";口味评价
bool flag2 = FoodEffect.IsHumanFlesh(food);是否为人肉
bool flag3 = FoodEffect.IsUndeadFlesh(food);是否有不净


接下来是一堆词条判定,就不放代码了,太乱
如果吃的食物不是烹饪过的菜,材质也不是肉,那它上面就算有人肉或不净词条也算非人肉非不净(flag2 = (flag3 = false))
如果食物是“deadbody”,那固定视为人肉(flag2 = true)
然后检测食物的配方,如果配方里有蛋,那这个食物上的人肉词条失效。就算类别不是蛋类料理,就算这个配方能放蛋但是你没放,也不行。
然后是如果肉是不死生物(不净)的肉,强制视为腐烂


接下来这段是对祝福以及人肉的判定,代码太乱所以也只贴结论:
如果食物是祝福的,那么num2*1.5
如果食物是诅咒的,那么num2*0.5
然后,接下来是对吃人肉的时候的判断食用者是否具有 flag4 = c.HasElement(1205):(推测是喜爱人肉词条))
如果吃的人喜欢人肉,且吃的是人肉:
食物倍率num2*1.5,评价倍率num5 * 2
如果吃的人喜欢人肉,但吃的不是人肉:
食物倍率num2*0.5,评价倍率num5*0.5,同时营养值num3减半
如果不喜欢吃人,且吃了人,那么
食物倍率num2*0.5,评价倍率num5=0
如果食用者c.HasElement(1200)(推测为朱伊安种族特质),则食物倍率num2*1.25
如果食用者!c.IsPC(非玩家) ,则食物倍率num2*3
接下来进行了一次食腐判断:如果腐烂且食用者没有食腐装备,那么营养值num3减半,同时评价倍率num5=0(赤到石了)
如果没有腐烂,则进行一系列的生食判断:
吃生肉,那么食物倍率num2 * 0.7,评价倍率num5固定为0.5f,同时玩家会吐槽
吃生鱼:食物倍率num2 * 0.9,评价倍率num5固定为0.5f,同时玩家会吐槽
吃生面团:食物倍率num2 * 0.9,评价倍率num5固定为0.5f,同时玩家会吐槽


接下来对营养值系数进行计算
float num6 = Mathf.Min(c.hunger.value, num3);
if (c.hunger.GetPhase() >= 3)
num6 *= 1.1f;
即取食物的营养值与玩家的饥饿值中较低的那个(也就是溢出的饱腹会浪费)
然后如果饥饿程度大于3(即饿了),营养值倍率* 1.1


然后在进行食物上的附魔词条的应用前,又进行了一次食腐判断
如果腐烂了且没有食腐装备:力量体质-300经验,灵巧感知学习-200经验,意志+500经验,魔力-200经验,魅力-300经验(不知道顺序对不对)。*不会获得食物上的词条的效果*
否则,才会开始应用食物上的各种词条


在应用食物词条时,首先对食物倍率num2更新,应用营养值倍率:
num2 = num2 * num6 / 10f;
然后如果玩家有厌食症,则倍率num2直接被设定为0.01
if (c.HasCondition<ConAnorexia>())
num2 = 0.01f;
接下来遍历食物上的词条,检测每个词条是否具有“foodEffect”,没有的话就跳过
然后将词条的值乘以食物倍率num2,得到num7(词条效果值)
词条的foodEffect[0]储存了该词条的类型(有exp,pot,karma等,对应经验潜力猫等等),不同类型执行不一样的效果:


如果该词条类型是经验值exp:
id = ((foodEffect.Length > 1) ? EClass.sources.elements.alias[foodEffect[1]].id : value.id);
int a = (int)(num7 * (float)((foodEffect.Length > 2) ? foodEffect[2].ToInt() : 4)) * 2 / 3;
c.ModExp(id, a);
可以看到词条效果值num7 在特定情况下会乘以另一个系数:
如果foodEffect.Length至少为2(也就是至少储存了3个值),那么最终经验会乘以 foodEffect[2]中的值再 * 2/3,否则最终经验是 * 4 再 * 2/3(也就是*8/3)不是很清楚这个foodEffect里的[1和2]都是存的啥。但是可以认为词条里有个值储存了它的“强度”,这个强度是不同属性类型固定的还是可以随食材效果改变的,不得而知(我倾向于不同类型有不同的固定值)
然后玩家获得最终经验值


词条类型是潜力pot:
id = ((foodEffect.Length > 1) ? EClass.sources.elements.alias[foodEffect[1]].id : value.id);
int vTempPotential = c.elements.GetElement(id).vTempPotential;
int num8 = EClass.rndHalf((int)(num7 / 5f) + 1);
num8 = num8 * 100 / Mathf.Max(100, vTempPotential * 2 / 3);
c.elements.ModTempPotential(id, num8, 8);
最终潜力num7的值/5 +1 之后的值会随机乘以 0.5~1(期望是*0.75)得到最终最终潜力num8
然后,得到的num8会除以(100/(当前临时潜力值 * 2/3)),但潜力低于150时不生效(不会使得值增加)
也就是临时潜力低于150时,全额获得潜力,高于150时,潜力越高,获得的潜力越少。300点额外潜力时,获得潜力减半
然后玩家获得该属性的潜力值


其它词条都是猫啥的(还有亚当),大家都知道效果,就不分析了,接着转入ProcTrait(Chara c, Card t)判断各种草药的治愈效果
然后根据一堆属性评价食物好不好吃(还有人肉口味评价),我是懒得分析这个
接下来是才是饱腹度的应用(接下来的饱食度修正应用在经验计算后):
num3 = num3 * (100 + c.Evalue(1235) * 10) / (100 + c.Evalue(1234) * 10);
两个特性应该分别是小胃和大食,每级增加/减少获得的饱腹度10%
然后修改食用者的饥饿值(减num3)


接下来更新食人者相关:
吃了人时:
食用者没有食人爱好:
如果食用者是人:增加200点不安定异常(c.AddCondition<ConInsane>(200)),同时增加15点疯狂(c.SAN.Mod(15))
如果食用者是人,则有1/5概率获得食人天赋,不是人则有1/20的概率获得食人天赋(EClass.rnd(c.IsHuman ? 5 : 20) == 0)
食用者有食人爱好:
c.SetInt(31, EClass.world.date.GetRaw() + 10080);
设定某个值,这里推测应该是食人特性过期的日期(当前日期+10080)
吃了不是人的食物时:
如果食用者喜欢吃人,且目前日期已经超过食人过期日期,那么失去食人特性(也就是说多吃非人食物并不会加速食人特性的失去)


然后如果吃了不净食物且没有食腐会获得一些debuff:
if (flag5 && !c.HasElement(480))
{
c.AddCondition<ConParalyze>();
c.AddCondition<ConConfuse>(200);
}


如果有厌食症则呕吐:
if (c.HasCondition<ConAnorexia>())
{
c.Vomit();
}


如果num3此时超过20,且具有特性1413,(num3 > 20 && c.HasElement(1413))
则吐种子(那就是小妖精特性)
所以让小妖精吐种子的前提是等效营养大于20,有人为了催吐给小妖精喂腐烂食物,是没有道理的(同时因为腐烂食物营养减半,需要40面板营养才能让她吐种子)


然后触发食物的其他食用特效(秒杀冒险者的毒词条大概是这里生效),如果食物是饮品,还会触发饮用特效
这就是整个食物判定流程了

总结,以及建议
比较值得注意的点是:
祝福1.5倍加成;人肉1.5倍加成;
品质的每级10%加成与用餐区10%加成是同一个区间,线性叠加
配方中带有蛋的料理不会被视为人肉


关于营养:
我个人的看法是长期来看营养的高低是没意义的。
食物提供的总经验会乘以营养总值,因此只看单个食物的时候,营养越高给的经验越多,看似营养越高越好。但是,营养越多,需要消化的时间也越多。营养溢出(吃撑了后面还有一些容量)确实会浪费,但是并不影响属性获取效率。长期来看,在等附魔值的前提下,料理营养的高低(就算溢出)不会影响属性获取的效率,因为玩家饥饿速率是恒定的(除了冤种朱伊安)。
举例来说,假设玩家每天消耗40营养值,那么2天吃俩40的面包和吃一个80的面包和吃一个120的面包(溢出部分无效)并无区别。因此从长期效率看料理只需要看上面的总附魔值(即附魔值*品质*人肉*祝福等)
在我们对比两个料理之前的强弱时,可以自行把面板附魔等级乘以人肉,品质等加成系数,换算后比较两个料理的优劣


关于人肉料理:
由于新版ban了带有蛋材料的料理作为人肉料理,儿童套餐拉了,但是我们依然可以用带人肉词条的奶酪/肉进行料理,需要sl,因为目前来看制作料理时会随机选择一个材料继承其蓝色词条,如果做出来没有人肉就需要读档走两步。
我觉得现在这个随机继承人肉词条可能是bug,以后也许会修复
bug影响我做人了.jpg
弄出来人肉奶酪之后做人肉料理应该还挺自由的,该放啥放啥就行(只是银铃蛋没法作为人肉料理材料了)。


关于潜力与经验词条取舍:
TODO

1 Comments
FatDoge 10 Dec, 2024 @ 11:42pm 
好傢伙 總結就是吃人肉是吧