当前位置:首页 > 日记

黑卡蒂的逃课工具箱-修改器py脚本手册

Python 脚本开发手册 & 主框架 API 接口文档本手册面向希望直接使用 Python 编写游戏修改脚本的开发者。框架同时支持 JSON 声明式脚本(推荐)和传统 Python 模块脚本,但掌握 Py

黑卡蒂admin

黑卡蒂的逃课工具箱Python 脚本开发手册 & 主框架 API 接口文档

本手册面向希望直接使用 Python 编写黑卡蒂的逃课工具箱游戏修改脚本的开发者。框架同时支持 JSON 声明式脚本(推荐)和传统 Python 模块脚本,但掌握 Python 接口有助于实现更复杂的自定义逻辑。


一、脚本结构与加载方式

1.1 传统 Python 脚本
脚本必须放在 scripts/游戏名/ 目录下,且该目录需包含 __init__.py 文件。
__init__.py 中必须暴露一个函数 get_ui(engine),返回一个 QWidget 实例。

python
# scripts/my_game/__init__.py
from .my_ui import MyGameWidget

def get_ui(engine):
    return MyGameWidget(engine)

1.2 JSON 脚本(推荐)
只需在 scripts/json/ 下放置符合框架规范的 .json 文件,无需编写 Python 代码。
JSON 脚本通过图形化生成器创建,详见《脚本生成器使用手册》。


二、核心引擎 API (MemoryEngine)

所有内存操作、基址解析、特征码扫描等功能均由 core.engine.MemoryEngine 提供。脚本通过 get_ui(engine) 获取其实例。

2.1 进程管理

方法 说明
attach(process_name: str) -> bool 附加进程,自动获取主模块基址。成功返回 True
detach() 断开当前进程连接。
is_attached() -> bool 返回是否已附加进程。
is_process_alive() -> bool 检查已附加的进程是否仍在运行。
get_module_base(module_name: str = None) -> int 获取模块基址,默认返回主模块基址。

2.2 内存读写

所有读写操作使用绝对地址。

方法 说明
read_int(address) -> int 读取 4 字节有符号整数
write_int(address, value) 写入 4 字节有符号整数
read_uint(address) -> int 读取 4 字节无符号整数
write_uint(address, value) 写入 4 字节无符号整数
read_short(address) -> int 读取 2 字节有符号短整数
write_short(address, value) 写入 2 字节有符号短整数
read_byte(address) -> int 读取 1 字节
write_byte(address, value) 写入 1 字节
read_float(address) -> float 读取 4 字节浮点数
write_float(address, value) 写入 4 字节浮点数
read_bytes(address, size) -> bytes 读取指定长度的原始字节
write_bytes(address, data: bytes) 写入原始字节数据

2.3 特征码扫描

python
pattern_scan(module_base: int, pattern: str) -> Optional[int]
  • pattern 格式:"0F 85 ?? ?? ?? ?? 48 8B 05"?? 表示通配符。

  • 返回匹配的绝对地址,失败返回 None

2.4 基址解析

python
resolve_base(config: dict) -> Optional[int]

根据配置字典自动计算最终地址。支持两种类型:

类型 1:固定偏移

python
{
    "type": "fixed_offset",
    "module": "sora_1st.exe",
    "offset": 0x123456
}

类型 2:特征码扫描 + RIP 相对偏移

python
{
    "type": "pattern_scan",
    "module": "sora_1st.exe",
    "pattern": "0F 85 ?? ?? ?? ?? 48 8B 05 ...",
    "offset_to_add": 6,   # 从匹配地址到目标指令的偏移
    "disp32_offset": 3,   # 位移量在指令内的偏移
    "instruction_length": 7  # 指令长度
}

该方法会自动读取 RIP 相对寻址中的位移量并计算出最终地址。

注意resolve_base 返回的是指针地址,而非最终的数据区基址。对于像空之轨迹 FC 这样的游戏,需要再执行一次 8 字节解引用才能获得真正的全局变量基址。框架已经内置此处理,通常无需手动干预;但如果你在 Python 脚本中直接调用 resolve_base,需自行解引用。

2.5 辅助工具

python
read_rip_relative_address(instruction_addr, disp_offset=3, instr_length=7) -> int

手动解析 RIP 相对寻址,返回目标地址。

2.6 音效反馈

引擎提供了统一的反馈接口:

python
engine.feedback(action_type: str)

其中 action_type 为 "activate"(成功/开启)或 "deactivate"(关闭/取消)。框架自动播放对应的提示音,无需脚本额外处理。


三、脚本界面规范

脚本返回的 QWidget 应当实现以下可选方法,以便与主框架深度集成:

方法 说明
on_attach() 当框架成功附加进程后调用,通常用于解析基址并刷新所有显示。
get_actions() -> dict 返回一个字典,键为动作名称,值为可调用对象(无参函数)。这些动作将出现在热键设置中。
execute_action(name) 执行指定名称的动作。框架热键触发时会调用此方法。

示例

python
class MyGameWidget(QWidget):
    def on_attach(self):
        self.resolve_bases()
        self.refresh_all()

    def get_actions(self):
        return {
            "heal_all": self.heal_all,
            "toggle_god_mode": self.toggle_god_mode
        }

    def execute_action(self, name):
        if name in self.get_actions():
            self.get_actions()[name]()

四、框架服务(主窗口接口)

脚本可以通过 engine 获取主窗口实例(如果需要),但通常不需要直接交互。
主窗口提供的公共方法(供生成器调用,一般不用于脚本):

  • load_script_from_file(file_path):加载指定 JSON 脚本文件并显示。


五、热键系统

框架使用 utils.hotkey_manager.HotkeyManager 管理全局热键。
脚本无需直接操作热键管理器,只需实现 get_actions(),用户即可通过“设置 -> 全局热键设置”为动作绑定快捷键。

热键对话框会显示所有动作名称和当前绑定,支持录制组合键。


六、配置文件

框架将用户设置保存在 config.json 中,包括:

  • 上次加载的脚本

  • 各脚本的热键绑定(以动作 ID 为键)

脚本不应直接修改此文件,但可以通过 utils.config 中的 get_hotkeys() / set_hotkeys() 读写热键配置(一般不推荐)。


七、迁移到 JSON 脚本

如果已经编写了 Python 脚本,可以考虑将其转换为 JSON 描述文件,以获得生成器的可视化编辑能力。转换规则:

  • 将基址解析逻辑写入 resolvers

  • 将地址计算写入 variables

  • 将界面控件描述写入 tabs

  • 将动作封装为 actions 中的步骤

使用生成器的“导入现有脚本”功能可以加载已有的 JSON 脚本进行编辑。


八、常见问题

Q:如何读取指针链?
A:目前基址解析器不支持多级指针,可在脚本中手动调用 read_int 跟随指针,或使用 read_bytes + int.from_bytes 组合。

Q:如何实现复杂的锁定逻辑(如全队生命锁定)?
A:使用 JSON 脚本的 checkbox 控件 + 关联动作,动作中定义 lock 步骤即可;Python 脚本则可借助 QTimer 和 engine.write_int 自行实现。

Q:框架是否支持 64 位游戏?
A:支持,所有读写操作默认使用 32 位类型,但可通过 read_bytes + 手动转换读取 64 位数据。

Q:如何让脚本兼容旧版框架?
A:框架会检查 manifest.json 中的 framework_version 字段,若高于当前版本会提示。建议在脚本中声明最低兼容版本。


九、API 版本历史

版本 说明
1.0 初始版本,包含 MemoryEngine、热键、悬浮窗、音效反馈、JSON 脚本支持。


返回顶部