辐射4吧 关注:312,450贴子:5,920,613

Idiot Savant Perk详细解析与测试

取消只看楼主收藏回复

开这个测试贴的初衷是为了研究吧里流传较广的一些关于Idiot Savant Perk(为防河蟹,以下简称为白吃学者或学者)的效果的观点,比如白吃学者3级的60秒3倍战斗经验能和2级的基础5倍经验效果叠加等一些观点的准确性。其中一些观点与我一直以来从ck或edit中了解的游戏数据得来的推论有些偏差。大家对学者perk效果的理解大多来源于Fallout wiki,wiki上绝大部分的信息都可以与游戏数据相吻合,但唯独对于学者3级的效果描述很少,且未对其触发机制进行过详细说明。为了测试perk的实际效果,需要进行有变量控制的游戏测试。正好前段时间自己的mod完工,又适逢游戏更新,我就趁这个机会开始了这次测试,希望能从游戏数据和脚本解读、总结推论和变量控制mod测试的角度来详细解析白吃学者perk的效果。
此贴中部分解释信息来源于脚本注释和ck wiki,前半部分为基础解析和总结推论,后半部分为变量控制mod测试和结论。测试所用的版本为1.10.130,所用工具中,ck版本为1.10.15,xedit版本为4.02,mo2版本为2.16。
我的mod技术并不算很高,C基础也差不多快还给大学老师了,Papyrus也只是了解了一些基础概念,现学现卖,因此部分解读和测试可能不完全准确和全面,而本贴的解读角度也与一些贴子不同,因此只作为抛砖引玉,不准确的地方欢迎大家指正。对于刚接触mod的玩家来说,如果这个贴子的内容能够引起你对mod制作和研究的兴趣,那自然是再好不过了。


IP属地:广东1楼2019-03-29 21:24回复
    一、基础概念解释
    用ck加载Fallout4.esm,在perk选项卡下用Idiot过滤,前三个perk就是白吃学者各个级别的perk,它们的editor id为:IdiotSavant01、IdiotSavant02和IdiotSavant03:


    IP属地:广东2楼2019-03-29 21:27
    收起回复
      1、perk信息
      打开IdiotSavant01,可以看到包含在白吃学者1级perk下的详细信息:

      ID:perk的editor id,用于ck从游戏信息里识别这条记录;
      Name:perk的名字,游戏里实际显示的文本;
      Perk Description:perk的详细描述,游戏里实际显示的文本;
      Icon:图标,游戏里未使用这个属性;
      Sound:声效,这里是将鼠标放在perk选择菜单的学者perk上面时,播放的冒泡声,【并非perk生效时的傻笑声】;
      SWF:动画文件,【此栏为空】;
      3个Flag标签:Trait,Playable和Hidden
      Trait:特性,将perk识别 为特性而非标准perk,这个属性未被游戏使用;
      Playable:玩家是否可用,决定是否出现在角色菜单里,是否升级后可选;
      Hidden:勾选时不会出现在角色菜单里;
      Level:perk可以选择的最小等级;
      MumRanks:perk总共几级;
      Next Perk:下一级perk;
      Level-Up Menu Conditions:perk点亮条件;
      Perk Entries:perk入口,perk的具体效果列表;
      Papyrus Scripts:perk相关的脚本;


      IP属地:广东3楼2019-03-29 21:38
      回复
        2、点亮条件
        perk的点亮条件Level-Up Menu Conditions栏下只有一个项目,打开这个条件:

        打开ObjectReference.psc,查找GetBaseValue,我们可以从制作人员的注释中查到一些相关信息:

        函数GetBaseValue(ActorValue akAV):从ObjectReference类型的对象akAV上,获得指定的ActorValue,返回一个浮点数;
        当玩家的幸运值大于等于5时,满足点亮白吃学者1~3级perk的条件;


        IP属地:广东4楼2019-03-29 21:45
        回复
          3、perk入口(perk的具体效果)
          白吃学者1级perk的perk入口栏Perk Entries下有11个项目,选取其中一个perk入口打开:

          Rank:等级,标示了perk入口何时运行,每给角色添加一次perk,perk等级就会+1,当一个perk入口需要适用于多个等级时,要分开单独指定;
          Priority:优先级,当两个perk入口影响同一个值时,决定它们的作用顺序,高优先级者优先;
          Quest:探索。游戏里的故事、冒险等,通常以任务的形式作为表现。这里的选项是使这个perk入口启用的相关任务;
          Stage:任务阶段。使这个perk入口启用的Spell ability,魔法,你没听错,你要知道esm全称就叫做Elder Scrolls Master,esp全称就叫Elder Scrolls Plugin
          Entry Point:入口点,在这里选择预定义好的代码模块,硬编码部分,无法新增;图中的效果是获得经验×3;
          Conditions:触发条件,这里拥有3个选项卡:Perk Owner,Weapon,Target;
          Perk Owner:从perk拥有者身上评估的条件;
          Weapon:从perk拥有者装备的武器上评估的条件;
          Target:从perk的目标上评估的条件;


          IP属地:广东5楼2019-03-29 22:00
          回复
            4、具体条件
            从前面的图中我们可以看到,这个等级1、优先级1的效果里有4个条件,最后均带有AND,且,所有条件均满足时才会生效;
            (1)条件1:

            打开Actor.psc,查找HasMagicEffect:

            函数HasMagicEffect(MagicEffect akEffect),检查是否受MagicEffect类型的法术效果akEffect影响,返回true或false;
            当perk拥有对象未受editor id为PerkIdiotSavantXPBootsEffect的法术效果影响时,满足条件1;


            IP属地:广东6楼2019-03-29 22:07
            回复
              (2)条件2:

              前面的图中,Actor.psc里从函数HasMagicEffect()开始往下数,第3个就是函数HasPerk(Perk akPerk);
              类似上面,检查是否拥有Perk类型的perk:akPerk的影响,返回返回true或false;
              当perk拥有者未拥有editor id为IdiotSavant02的perk,即白吃学者的2级perk时,满足条件;
              (3)条件3:

              从ObjectReference.psc中可以找到函数GetValue(ActorValue akAV);
              与前面的函数GetBaseValue()类似,从ObjectReference类型的对象akAV上获得ActorValue,返回一个浮点数;
              当perk拥有对象的智力等于1时,满足条件3;
              (4)条件4

              条件类型函数GetRandomPercent,【返回1个范围在0-99内的int型随机数】;
              与10相比,只有0~10范围内的【11个】int型数满足小于等于10的条件,【概率为11%】;
              综上4个条件,在白吃学者1级perk中,这个等级1,优先级1的效果为:当perk拥有者的智力等于1、没有白吃学者2级perk,不受法术效果PerkIdiotSavantXPBootsEffect影响时,有11%概率获得3倍经验。


              IP属地:广东8楼2019-03-29 22:22
              回复
                5、脚本
                从perk信息下,可以看到与1~3级的白吃学者perk相关的脚本名称叫做IdiotSavantScript,打开IdiotSavantScript.psc,可以看到这个脚本的Papyrus代码;


                IP属地:广东9楼2019-03-29 22:28
                回复
                  第1行定义了脚本的类型和名称,IdiotSavantScript是脚本的名称,extends定义了该脚本是基于Perk Script的扩展脚本,因此,在这个脚本里,可以调用Perk.psc里已定义的事件响应和函数;
                  第12~15行定义了4种Auto类型的属性并赋初始值,其中:
                  第12行定义了名称为Yeah的Sound类型的属性;
                  第13行定义了名称为IdiotSavantXPBoostSpell的Spell类型的属性;
                  第14行定义了名称为IdiotSavant03的Perk类型的属性;
                  第15行定义了名称为idiotSavantSwfName的String类型的属性,并赋初始值为Components\\VaultBoys\\Perks\\PerkClip_1d245e.swf;
                  打开ck中白吃学者某一级perk信息界面下Papyrus Scripts栏下的Properties选项,可以查看这4个属性的最终赋值:

                  4个属性的赋值分别为:
                  Yeah:赋值为editor id为UIPerkIdiotSavant的声音,【这才是我们熟悉的傻笑声】;
                  diotSavantXPBoostSpell:赋值为editor id为IdiotSavantXPBoostSpell的法术;
                  IdiotSavant03:赋值为editor id为IdiotSavant03的perk,即学者的第3级perk;
                  idiotSavantSwfName:赋值为Components/VaultBoys/Perks/PerkClip_1d245e.swf;
                  解包Fallout4 – Interface.ba2,找到路径Interface\Components\VaultBoys\Perks文件夹下名为PerkClip_1d245e.swf的动画文件,可以发现正好是学者1~3级perk生效时播放的避难所小子动画:


                  IP属地:广东11楼2019-03-29 22:53
                  回复
                    脚本的第3~10行,Event到EndEvent的范围内的内容是事件响应,这部分解释了这个脚本是如何对OnEntryRun(intauiEntryID, ObjectReference akTarget, Actor akOwner)这个Perk Script类型的事件函数进行响应的;()内规定了将从游戏中发送哪种类型的参数到OnEntryRun()事件响应中,auiEntryID、akTarget和akOwner是这个函数的特殊参数的名称,int、ObjectReference和Actor是参数类型,其中:
                    auiEntryID:运行的perk入口的id;
                    akTarget:perk入口的目标;
                    akOwner:perk的拥有者;
                    打开Perk.psc,查找OnEntryRun:

                    函数OnEntryRun(int auiEntryID, ObjectReferenceakTarget, Actor akOwner):当一个perk入口运行时,做出响应;


                    IP属地:广东12楼2019-03-29 23:01
                    收起回复
                      第4行,调用Game Script中定义的ShowPerkVaultBoyOnHUD()函数;
                      打开Game.psc,查找ShowPerkVaultBoyOnHUD:

                      函数ShowPerkVaultBoyOnHUD(string aVaultBoySwf, Sound aSoundDescriptor = None):在HUD界面上播放字符串型参数aVaultBoySwf和Sound参数aSoundDescriptor,其中,Sound参数aSoundDescriptor的预设值为无;
                      因此,第4行的解释为:播放第15行中定义的String属性idiotSavantSwfName的赋值动画和第12行中定义的Sound型属性Yeah的赋值声音;


                      IP属地:广东13楼2019-03-29 23:08
                      回复
                        第5行,调用Game Script中定义的IncrementStat()函数;
                        同样,可以在Game.psc中找到函数IncrementStat(string asStatName, int aiModAmount = 1):增加名称为asStatName的杂项统计信息的数量,数量为aiModAmount,预设值为1;
                        因此,第5行的解释为:增加杂项信息统计中Bright Ideas的数量1;


                        IP属地:广东14楼2019-03-29 23:12
                        回复
                          第7~9行中,if到endif的范围内为条件判断执行;
                          第7行,因为事件响应OnEntryRun()的特殊参数akOwner为Actor类型,因此可以调用Actor Script中已定义的函数HasPerk(),从前文可知,HasPerk()是一个bool型函数,返回true或false,因此可以与条件中的true进行对比;
                          函数HasPerk(IdiotSavant03),判断是否拥有第14行中定义的Perk型属性IdiotSavant03的赋值perk,返回true或false;
                          akOwner调用函数asPerk(),判断一个perk入口运行时,这个perk入口所属的perk拥有者是否拥有某个perk;
                          因此第7行的解释为:当某个perk入口运行时,这个perk入口所属的perk的拥有者,拥有白吃学者的第3级perk时,继续执行,否则什么也不做;


                          IP属地:广东15楼2019-03-29 23:20
                          回复
                            第8行,在第13行中定义的Spell属性调用Spell Script中已定义的函数cast();
                            函数Cast(ObjectReference akSource, ObjectReference akTarget = None):将ObjectReference类型的法术akSource,向ObjectReference类型的目标akTarget释放,其中,akTarget的预设值为无;
                            因此第8行的解释为:运行的perk入口的所属perk的拥有者akOwner,释放第13行中定义的Spell属性IdiotSavantXPBoostSpell的赋值法术;


                            IP属地:广东16楼2019-03-29 23:28
                            回复
                              综上,整个脚本的解释为:
                              当玩家的某级白吃学者perk生效时,在HUD上播放避难所小子动画和傻笑声,并在统计信息中+1,如果拥有白吃学者的第3级perk,则释放editor id为IdiotSavantXPBoostSpell的法术。


                              IP属地:广东17楼2019-03-29 23:31
                              回复