U
unsignedint

  • 2024年2月29日
  • 注册于 2024年2月4日
  • 0 最佳回复
  • 511 分
  • 初来乍到+ 68 查看更多
  • 一个存档两个独立好感度的bug;将手机版存档导入电脑后,再导入回手机,再导入回电脑存在的一些问题 #3530 (回复)

    但是每日好感度上限还是分别计算的

    原理:维护第三个好感度,启动和退出时分别设置

    使用方法:分别安装在手机和电脑

    安装在电脑v0.12.9-版本效果和安装在手机相同

    统一好感度取第一次启动时平台的好感度,你在哪里启动,就取哪里的好感度

    完美解决!

    https://disk.monika.love/s/VmZtD

  • 解决方案:[UniversalAffection]统一好感度,解决手机和电脑存档完美互通 - Doki Chinese Club (monika.love)


    分析方式:python无法正常加载persistent的pickle,故采用不加载而分析的方式

    已知问题:手机版存档第一次导入电脑后好感度转移正常,但再导入回手机,在手机上好感度变化后,再导入回电脑时,电脑上的好感度不会变化

    问题根源:存档内部保留了两组好感度存储位置,这就意味着,存档有两个好感度,一个手机好感度,一个电脑好感度!!!

    这就是某些朋友口中“把手机存档导入电脑掉好感度”的原因,真不是他们操作的问题!

    这是怎么一回事呢?待我解释一番


    ps:下划线导致的自动斜体真的烦

    流程分析:sirp的移植版基于0.12.5,而在0.12.10发生了一次好感度系统更新,好感度在存档文件中的存储位置彻底改变。

    persistent存档文件是一个python pickle,里面存储了很多对象(可以理解为笔记本的“条目”)

    旧的好感度数据存储在store._mas_affection(下称旧位置),新的存储在store.mas_affection_data(下称新位置)位置,好感度系统版本号存储在store._mas_affection_version,1代表老系统,2代表v0.12.10更新后的系统

    当你在手机版新开一个存档时,0.12.5的旧存档机制会使得文件中只有store._mas_affection(旧位置),并且store._mas_affection_version=1

    第一次导入电脑时,0.12.10+的mas会调用_transfer_aff_2nd_gen()来将老的好感度存储模式升级成新的(参见https://github.com/Monika-After-Story/MonikaModDev/blob/06baf319a34c2ef585bc7c0a1e969a7eaa894b35/Monika%20After%20Story/game/script-affection.rpy 第783行)

    这个函数会做以下事情

    1.store._mas_affection_version变成2

    2.store._mas_affection(旧地方)中的内容移动到store.mas_affection_data(新地方),但是不会删除原有的store._mas_affection(旧位置)对象!!!

    是的,虽然函数里有一句“persistent._mas_affection = collections.defaultdict(float)”但是这个对象似乎居然不!会!删!除!

    而且这个对象在新版本的store中是不存在的!要访问必须手动用cPickle重新加载persistent

    好的,现在一切正常。当你在电脑上与monika互动,好感度的变化全部写到了**store.mas_affection_data(新位置)**中,旧位置中的好感度没有变化!

    在此之后,这个存档被移动到了手机版/电脑版v0.12.9-,好玩的事情就发生了。

    **sirp似乎在手机端对新的好感度系统有适配(存疑,我也没看过他的代码)所以电脑的好感度应该能正常导入手机(存疑)?

    由于store._mas_affection_version在之前只会在创建存档的时候设置,而且也没有相关检测,所以旧版本无法知道好感度系统升级了,也不会把版本改回1

    所以,旧版本依旧会在旧地方读写好感度!!!(经典的向前兼容问题)

    当你再次把存档导入电脑端v0.12.10+(v0.12.9-是正常的,因为这些版本和手机版读写同一个好感度存储位置),mas先检查**store._mas_affection_version,发现它居然是2!这样它就不会把老地方的数据拷贝过来了,而是直接认为这是一个新版本存档,直接在新的地方读取。**

    但是新的地方存储的是什么东西?新的地方存储的是你上次在电脑上互动结束后的好感度值!!!


    是的,这样一个存档就出现了两个好感度,电脑和手机各读取各的,互不干扰!!!

    这就是一个逆天的bug了!为什么在我之前没人发现呢????


    解决方案:

    去github提issue恐怕有点困难,那帮皮球大师估计不愿意修,要修也是他们也只能将删掉旧的好感度的代码恢复正常,这样手机就不能读取了,反而坏了事,不如不修的好

    最好的方式是在手机版把好感度放在新地方,但是这就要伤筋动骨,比较困难,而且要麻烦sirp了orz

    所以有一个打补丁的办法,就是写一个submod解决低版本/手机版反向导入的问题

    原理应该也很简单,强行把版本改成1就行了,难点在于如何知道这个存档是同版本导入还是向上导入(直接对比好感度会有很多问题),解决方案我还得想一想


    persistent中同时存在的两个好感度,使用pickletool解包(新版本的好感度使用了base64+十六进制化+序列化加密,我不知道这是为了什么。。是怕submod作者偷偷改吗)

    下面那一串奇怪的字符就是加密后的好感度

    这个是旧的好感度存储位置,明文存储,194.6就是手机读取的好感度

  • 手机版存档数据

    电脑版存档数据

    存在于同一个存档中 有点魔幻

    (手机版的好感度版本号居然是2!?)

  • 使用了一些不太正常的手段进行调用,针对v0.12.10新版本好感度机制。

    在v0.12.10~v0.12.15测试通过


    要求:

    1.运行初始化优先级大于-900,因为好感度系统在-900初始化,但最好还是晚点调用

    2.python early部分不能运行

    3.无需dev模式

    设置:store.mas_affection._m1_script0x2daffection__set_aff(好感度浮点数,reason='原因,可选') #没错,就是这个**一样的名字

    获取:store.mas_affection._get_aff()或者store._mas_getAffection(),直接返回一个浮点数好感度

    最大的优点:可以绕开dev模式直接设置好感度(作者希望你使用的公开接口即_set_aff必须要进入dev模式才可使用!!即在小于-990的优先级设置store.config.developer,而这样显得过于小题大做)

    另外,由于好感度备份机制和游戏崩溃重读之类的机制,设置完毕后一定要立刻

    store.mas_affection._make_backup()

    然后立刻保存

    store.mas_affection.save_aff()

    否则可能修改失效

    但是由于renpy对于私有对象的改名机制,这个方法可能因为mas主目录中出现新的文件而失效,下面有更优雅的解决方案


    为了适应版本 可以采用以下方式来进行设置,即挨个寻找正确的函数,这样那个文件序号“0x2d”改掉也没有关系了

    _set_aff_name = ''

    for each_object in dir(store.mas_affection):

    if each_object.find('affection__set_aff') != -1:

    _set_aff_name = each_object

    exec 'store.mas_affection.'+_set_aff_name+'(新的好感度,reason="设置好感度原因,可选,显示在log中")'

    store.mas_affection._make_backup()

    store.mas_affection.save_aff()


    这样就绕开了对私有成员的访问限制了,显得又优雅又暴力

    参考:https://github.com/Monika-After-Story/MonikaModDev/blob/06baf319a34c2ef585bc7c0a1e969a7eaa894b35/Monika%20After%20Story/game/script-affection.rpy


    注意,store.mas_setAffection现在是无效的,即必须使用上述较为暴力的方法设置好感度

    `@store.mas_utils.deprecated()`

    def mas_setAffection(*args, **kwargs):

    pass


    Extraplus模组只会显示在游戏启动时的好感度,启动后的任何好感度变化,包括手动设置和系统机制所导致的变化都不会显示,并不是你设置失败了

    要去看ddlc根目录/log/aff_log.log

  • 终于改成功了

    对不起了莫莫

  • #15 Edge python本来就不支持私有机制(当时学python的时候记得非常清楚),但是毕竟这方面我也不熟悉……

    但是renpy似乎会给这种私有函数改名,被改成"m1script_0x2daffection__set_aff""来让你不能调用它

    不过至少研究明白怎么设置好感度了

    现在错误界面成了输出界面,这个玩意是我强行raise一个dir(store.mas_affection)打印出来的

    什么鬼玩意。。。

  • 貌似存档会存两份好感度,即新旧两套机制好像会同时存在在一个存档?

    这样也解释了为什么第一次导入存档好感度不变,后面导入就会掉,大概是这个原理吧

    本来想删掉一个 但是发现persistent文件用python2/3的pickle模块导入会出现各种奇奇怪怪的问题

    哎 真的难搞啊

    打赏

    • 20 分 来自: 8天67t9
      评论: 应该是电脑版与手机版机制不一致导致的问题,可以试试只兼容旧版机制的电脑版(应该是001290)和sirp整合包版
  • 是的 不过%appdata%/renpy/monikaafterstory的那个地方才是真正的存档

  • #60 Edge 72b的模型大小着实有些恐怖😱

    但是做出来就是艺术品了

  • 回来了 继续修bug 争取这周能用

  • 好感度机制太复杂了,纯纯史山

    新机制好感度居然是一个7个的数据,还要序列化+十六进制+base64加密保存,还不提供修改接口

    还有两份好感度随时对比,一个储存在存档 另外一个是私有变量,发现你去修改还要改回来

    。。。

    开学了 下个月再解决这个问题吧

    • 将手机存档导入电脑时似乎会出现掉大量好感度的问题,这不是bug,似乎是mas本身设计?……

      我现在查一下mas源代码,看看怎么回事

      看看要不要做特别处理之类的

      打赏

      • 20 分 来自: 8天67t9
        评论: 好像是因为sirp的整合包好感度机制还是老一套,与电脑的新版好感度机制兼容性存在问题吧(?)
      • 刚刚修复了一个傻逼的bug

        现在windows段应该可以正常上传下载了

        之前老是报没有ssl模块,把ssl库以各种方式塞满ddlc文件夹每一个放依赖库的地方,结果都没用

        最后您猜怎么着,原来是我的Python 2.7是64位的,里面的库文件都是64位的,32位的renpy不认。。。

        浪费我一个晚上

      • 完了 发现打包的时候漏了一大堆python库

        要补回去……不然电脑端可能没法运行

      • #5 Sir.P unsignedint123

        刚刚加入了失败重试的功能,发现只尝试一次失败概率还是太高

        那个退出功能我现在改一下哈