Skip to content

About

《女神异闻录3 Reload》Steam 版存档修改器 —— 改人格面具技能/等级/经验/五维,自带加解密,无需 MOD

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

P3R-Save-Editor

《女神异闻录3 Reload》(Persona 3 Reload) Steam 版存档修改器。

纯离线文件读写,自带加解密,无需安装任何 MOD、不注入游戏进程。支持修改人格面具(Persona)的技能、等级、累计经验、五维,以及按数值 ID 直接改任意数据(金钱等)。

逆向成果与工具均为原创整理,已在实机存档上验证通过(Steam 版,UE4.27 GVAS)。


目录


下载

方式一:直接下载压缩包(推荐给只想用的人)

到 Releases 页面下载 P3R-Save-Editor-v1.1.zip,解压即用,里面已经包含全部脚本和使用说明。

方式二:克隆仓库(推荐给想改代码的人)

git clone https://github.com/anyiim/P3R-Save-Editor.git

两种方式得到的内容一样,脚本只依赖 Python 标准库,不需要 pip install 任何东西。


功能

功能 说明
列出 Persona 槽位 只读查看存档里全部人格的编号、等级、经验、五维、技能
修改 Persona 技能 最多 8 个技能,自动补/删技能槽
修改 Persona 等级 与累计经验配套写入
修改 Persona 累计经验 避免被游戏按经验反算回等级
修改 Persona 五维 力 / 魔 / 耐 / 速 / 运,每项 0~255
按 ID 改任意数值 金钱、日期、社群等级等,只需知道数值 ID
完整性校验 对比改档前后,确认只有目标记录被改动
加解密 可单独导出解密后的存档,便于自行分析

环境要求

  • Python 3.8+(仅用标准库:struct / argparse 等)
  • Windows(存档路径默认在 %APPDATA% 下)

非 Windows 系统理论上也能跑(脚本本身跨平台),但存档路径需要自己指定。


快速开始

第 1 步 · 找到你的存档

%APPDATA%\SEGA\P3R\Steam\<SteamID>\SaveData00X.sav

例如:

C:\Users\<你的用户名>\AppData\Roaming\SEGA\P3R\Steam\76561197960285355\SaveData004.sav

第 2 步 · 关闭游戏和 Steam

这一步不能省。 游戏运行时存档数据在内存里,你改完文件它一保存就会覆盖掉你的修改;更糟的情况是直接写坏存档。

第 3 步 · 备份原档

cd C:\Users\<你的用户名>\AppData\Roaming\SEGA\P3R\Steam\<SteamID>
copy SaveData004.sav SaveData004.sav.bak

第 4 步 · 生成修改后的存档

脚本不会改你的原档,而是读原档、输出一个新文件:

python p3r_editor.py SaveData004.sav 新档.sav --persona-code 0134 --skills 117,792,793,875,897,834,885,856 --dump

第 5 步 · 校验(可选但强烈建议)

python verify.py SaveData004.sav 新档.sav

输出会列出被改动的数值 ID,并确认其余记录一动没动:

对比: SaveData004.sav  ->  新档.sav
[OK] 加密往返自检 (encrypt(decrypt(x)) == x)
     原始: 375720 字节 -> 修改后: 375720 字节 (差 +0)
[OK] 记录数: 7616 -> 7616 (+0)
删除的 ID (0 条): []
新增的 ID (0 条): []
数值变化的 ID (1 条): ['7257 (90244->9999999)']
[OK] 其他 7615 条记录数值未被触碰
[OK] 原始: 记录间距=[49]  ID升序=True  终止符偏移=0x5bb9b
[OK] 修改后: 记录间距=[49]  ID升序=True  终止符偏移=0x5bb9b

[结果] Persona 0134 (槽0, base=13090)
       技能   : [117, 792, 793, 875, 897, 834, 885, 856]
       原技能 : [117, 792, 793, 875, 897, 834, 885, 856]
       等级   : 99  exp: 2000000

想让脚本额外复核某个指定人格,加 --persona-code;不加则自动复核第一个非空槽位。

第 6 步 · 写回游戏目录

把 新档.sav 复制回存档目录,改名成 SaveData004.sav 覆盖原文件即可。

下次启动如果 Steam 提示「云存档冲突」,选本地文件,否则云端旧档会把你的修改冲掉。


命令详解

基本用法

python p3r_editor.py <输入.sav> [输出.sav] [选项]

输出文件可省略 —— 配合 --list-persona 就能只读地查看存档,不写任何文件。

选项

选项 说明
--list-persona 只读,列出存档中全部 Persona 槽位(编号 / 等级 / 经验 / 五维),无需输出文件
--persona-code Persona 编号:完整编号如 0134(推荐),或旧简写如 3401
--skills 最多 8 个技能 ID,逗号分隔;不足会自动补空槽,超出会报错
--level 等级(需配合 --persona-code)
--exp 累计总经验(详见下方「关于累计经验」)
--stats 五维:力,魔,耐,速,运,每项 0~255
--set 直接指定 数值ID=值,可重复使用
--plain 强制输出未加密的 GVAS(默认跟随输入格式,见下)
--encrypt 强制输出加密存档
--dump 写出后重新读回并打印结果

输出格式默认跟随输入:喂加密的 .sav 进去就得到加密的存档;喂解密后的明文 GVAS 就得到明文。 需要强制指定时用 --plain / --encrypt。

先看看存档里有什么

不确定编号时,先只读地列一遍,这个操作不会修改任何文件:

python p3r_editor.py SaveData004.sav --list-persona
槽位  Persona  等级  累计经验       力/魔/耐/速/运
   0   0134     99     2000000     99/99/99/99/99
        技能: 117(空间杀法), 792(斩击强化), 793(高级斩击强化), ...
   1   0040      3         136     3/4/3/4/3
        技能: 155, 10

实例

① 换成物理斩击流配装(8 个技能)

python p3r_editor.py 输入.sav 输出.sav --persona-code 0134 \
  --skills 117,792,793,875,897,834,885,856

② 等级 + 经验一起拉满

python p3r_editor.py 输入.sav 输出.sav --persona-code 0134 \
  --level 99 --exp 2000000

③ 五维拉满

python p3r_editor.py 输入.sav 输出.sav --persona-code 0134 \
  --stats 99,99,99,99,99

④ 改金钱(7257 = 金钱)

python p3r_editor.py 输入.sav 输出.sav --set 7257=9999999

⑤ 组合使用

python p3r_editor.py 输入.sav 输出.sav \
  --persona-code 0134 \
  --skills 117,792,793,875,897,834,885,856 \
  --level 99 --exp 2000000 \
  --stats 99,99,99,99,99 \
  --set 7257=9999999 \
  --dump

辅助脚本

脚本 用法
verify.py python verify.py 原档.sav 新档.sav —— 改档前后完整性对比
p3r_crypt.py python p3r_crypt.py decrypt 存档.sav 输出.raw —— 单独解密存档,便于自行分析结构;info 子命令可只看格式与大小

技能 ID 对照表

Persona 编号

槽位里存的数值是 (编号 << 16) | 0x0001 —— 也就是高 16 位才是完整编号,低 16 位是固定的 0x0001 标记。

Persona 完整编号 旧简写
灰姑娘 (Cinderella) 0134 3401

推荐用完整编号(--persona-code 0134)。

旧的四位简写 3401 仍然能用,但它只保留了编号的低字节,所以 0040 和 0140 都会写成 4001 而撞车。 遇到这种情况脚本不会猜,而是直接报错并列出候选槽位,让你改用完整编号:

编号 4001 同时匹配到 2 个槽位, 无法确定改哪一个:
    槽1 (base=13102)  完整编号 0040
    槽3 (base=13126)  完整编号 0140
请改用完整编号, 例如: --persona-code 0040

其他 Persona 的编号不用查表 —— 用 --list-persona 直接从存档里读出来,这是最可靠的方式。

斩击 / 物理流常用技能

技能(中文) 英文名 ID
空间杀法 Vorpal Blade 117
斩击强化 Slash Boost 792
高级斩击强化 High Slash Boost 793
终极斩击强化 Ultimate Slash Boost 875
全体攻击强化 Multi-Target Boost 897
建言(暴击率 ×2) Apt Pupil 834
暴击大UP Critical Rate Amp 885
武道的资质(HP 消耗减半) Arms Master 856

其他常用

技能 / 项目 ID
神经碎断 121
玛哈克加 60
金钱 7257

完整技能表可查 Persona 3 Reload 官方中文 Wiki 的「技能列表」,编号与英文技能数据表一致。 以上 ID 均已通过官方中文 Wiki 与实机存档双向验证(例如存档中原本带有的「终极斩击强化」实测就是 875)。


存档格式备忘

以下是从实战中逆向出来的完整格式,供想自行扩展功能的人参考。

加密层(Steam 版)

Steam 版存档是加密的,但算法很简单,是 XOR + 半字节交换:

密钥:ae5zeitaix1joowooNgie3fahP5Ohph   (32 字节,循环使用)

解密:
  b = ciphertext ^ key
  plain = ((b >> 4) & 0x03) | ((b & 0x03) << 4) | (b & 0xCC)

加密:把上面的步骤反过来
  • 加密文件的魔数:0x0B650015
  • 解密后的魔数:GVAS

GVAS 层

解密后是标准 Unreal Engine 4.27 SaveGame:

  • 存档类名:/Script/xrd777.XRD777SaveGame
  • 游戏数据被拍平成一串名为 SaveDataArea 的 UInt32Property
  • 单条记录固定 49 字节:
偏移 长度 内容
+0 17 SaveDataArea\0(属性名)
+17 19 UInt32Property\0(类型名)
+36 4 04 00 00 00(固定)
+40 4 数值 ID(小端 u32)
+44 1 00
+45 4 值(小端 u32)
  • 记录按数值 ID 升序排列
  • value == 0 的条目不写入
  • 文件末尾终止符:05 00 00 00 "None\0"

Persona 槽位

base 序列为 13090 + 12 * k(k = 0…6,共 7 个槽位;空槽的 value 为 0,不会出现在文件里):

偏移 含义
+0 Persona 编号:(编号 << 16) | 0x0001,高 16 位是完整编号,低 16 位固定 0x0001
+1 等级
+2 累计总经验
+3 … +6 技能(4 个 u32)
+7 力 / 魔 / 耐 / 速(4 个 u8 打包)
+8 运

槽位顺序 = 队伍里的排列顺序,会随游戏操作变化,所以别按槽位号记,认编号。

13090 + 12 * k 之外也有长得很像的位置(例如 base + 12 * 12),但那些是别的数据结构 —— 按固定区间扫这 7 个槽位才可靠,全局扫描会产生大量误报。

技能打包规则:每个 u32 里装 2 个技能,高 16 位在前,低 16 位在后。所以 4 个字段最多容纳 8 个技能。

关于累计经验

存档里的 exp 存的是从 Lv1 起的累计总经验,不是当前等级的进度条。

证据是从多个存档里采样到的 (等级, 经验) 数据点:

(2, 67)  (3, 136)  (6, 912)  (34, 135042)
(36, 159737)  (50, 376259)  (89, 1390631)

这些点严格随等级单调上升、横跨三个数量级——如果是「当前级进度值」,不同 Persona 不可能排得这么整齐。

所以等级和 exp 必须一起改。 只改等级,游戏下次结算经验时会按 exp 把你算回原来的等级。

Lv99 需要的累计经验用幂律模型外推约 1.82M ~ 1.84M,写 2000000 有约 9% 余量。


常见问题

Q:会不会被封号? 不会。这是纯离线文件修改,不修改游戏本体、不联网、不涉及任何多人要素。和市面上其他 P3R 存档编辑器原理相同。当然,使用风险请自行承担。

Q:改完进游戏发现没变化? 三个常见原因:

  1. 游戏/Steam 在改档时没关,存档被覆盖了 —— 重来一次,先关游戏。
  2. 写回时文件名不对(必须是 SaveData004.sav)。
  3. Steam 云同步用云端旧档覆盖了本地 —— 冲突时选「本地文件」。

Q:五维改成 99 之后还能升级吗? 能升级,但属性不会再涨(已经是上限)。如果想要正常成长曲线,建议改成 40~60。

Q:改完存档损坏了 / 想反悔? 用第 3 步备份的 .bak 文件复制回去覆盖即可。所以备份真的很重要。

Q:技能 ID 写进去不生效? 确认 ID 是否正确。部分技能在存档里的编号与 Wiki 展示的编号存在换算关系,遇到不生效的情况可以对照存档中已有技能的数值反推。

Q:我不知道要改的 Persona 编号是多少? 跑 python p3r_editor.py 存档.sav --list-persona,它会只读地列出全部槽位的完整编号、等级、经验、五维和技能。这比查表可靠,因为它读的就是你这份存档。

Q:为什么编号 4001 会报「匹配到多个槽位」? 旧的四位写法只保留了编号的低字节,0040 和 0140 简化后都是 4001,无法区分。报错信息会列出每个候选的完整编号,挑你要的那个写进去即可。

Q:能直接写 --level 0 把等级清零吗? 游戏本身就不保存值为 0 的记录,所以写 0 等于删除那条记录。脚本会明确提示「值为 0: 已按游戏规则删除该条目」,不会静默处理。

Q:支持 Xbox Game Pass / PS 版吗? 不支持。目前只针对 Steam 版的加密格式,其他平台的存档结构不同。


仓库结构

P3R-Save-Editor/
├── README.md                         本文档
├── p3r_editor.py                     主工具(加解密 + 定位 + 修改)
├── verify.py                         改档前后完整性对比
├── p3r_crypt.py                      独立加解密工具
└── dist/
    └── P3R-Save-Editor-v1.1.zip      打包好的压缩包(解压即用)

更新记录

v1.1

  • 修复 Persona 定位可能撞车:编号的完整值在槽位的高 16 位,旧的四位简写只保留了低字节, 0040 与 0140 简化后都是 4001。现在优先按完整编号匹配,命中多个候选时明确报错并列出, 不再"猜"一个改掉。
  • 新增 --list-persona:只读列出存档中全部人格的编号 / 等级 / 经验 / 五维 / 技能。
  • 数值越界不再静默溢出:五维超过 255、技能 ID 超过 65535 现在直接报错 (此前会溢出并污染相邻字段,例如写「力=300」会读回 44)。
  • 输出格式跟随输入:喂明文 GVAS 进去不再被擅自加密;需要强制指定时用 --plain / --encrypt。
  • 写入 0 的行为明确提示:游戏不保存值为 0 的记录,因此写 0 等价于删除该条目,现在会打印提示。
  • verify.py 不再硬编码人格编号,且可在任意目录调用(此前依赖当前工作目录)。
  • p3r_crypt.py 的输入校验由 assert 改为显式报错,避免 python -O 下被跳过。

v1.0

初始版本。


免责声明

本项目仅供个人学习与存档备份用途。请勿用于商业传播。

使用本工具修改存档造成的任何后果(包括但不限于存档损坏、游戏体验异常、账号风险)由使用者自行承担。修改前请务必备份原档。

本项目与 ATLUS / SEGA 无任何关联,《女神异闻录》系列相关商标与版权归其各自所有者所有。

About

《女神异闻录3 Reload》Steam 版存档修改器 —— 改人格面具技能/等级/经验/五维,自带加解密,无需 MOD

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages