
游戏开发插件系统【免费下载链接】REPENTOGONScript extender for The Binding of Isaac: Repentance项目地址https://gitcode.com/gh_mirrors/re/REPENTOGON点击查看免费下载SpecialQuest是 REPENTOGON《The Binding of Isaac: Repentance》的脚本扩展中用于控制**特殊任务关卡门Knife Piece puzzle door**生成逻辑的核心枚举。它通过Level:GetForceSpecialQuest()/Level:SetForceSpecialQuest()等 Lua API 暴露给模组作者允许你在任意关卡阶段强制生成、恢复默认或彻底禁用刀片谜题门。读完本文你将掌握该枚举全部取值的行为差异、底层状态存储与 ASM 补丁实现并能写出可实际运行的模组代码来操控第一、第二块刀片谜题的触发。SpecialQuest 枚举总览该枚举的官方定义位于 docs/docs/enums/SpecialQuest.md完整取值如下ValueEnumeratorComment-1DISABLED0DEFAULT1MIRROR2MINESHAFT在 Lua 运行时环境中REPENTOGON 通过捆绑脚本 repentogon/resources/scripts/enums_ex.lua第 2971–2976 行将同名全局表注入解释器SpecialQuest { DISABLED -1, DEFAULT 0, MIRROR 1, MINESHAFT 2, }该脚本由 repentogon/LuaInit.cpp 中的RunBundledScript(resources/scripts/enums_ex.lua)在引擎初始化时执行因此所有模组在运行时都能直接引用SpecialQuest.DISABLED、SpecialQuest.MIRROR等常量无需自行定义数字字面量。枚举值语义解析DISABLED -1彻底关闭特殊任务门当ForceSpecialQuest被设为-1时无论当前所处 StageType 是什么游戏都不会尝试生成 Knife Piece 谜题门。这一点在 repentogon/Patches/ASMPatches/ASMLevel.cpp 的SpawnSpecialQuestDoorValidStageTypeCheck中有最直接的体现bool __stdcall SpawnSpecialQuestDoorValidStageTypeCheck() { // Always return true if we forced it via Room:TrySpawnSpecialQuestDoor bool ret roomASM.ForceSpecialQuestDoor; // If ForceSpecialQuest is -1, quest doors are disabled if (!ret levelASM.ForceSpecialQuest -1) { // ForceSpecialQuest 0 defaults to vanilla behavior ret levelASM.ForceSpecialQuest 0 || (g_Game-_stageType 4 || g_Game-_stageType 5); } roomASM.ForceSpecialQuestDoor false; return ret; }注意这里的条件判断levelASM.ForceSpecialQuest -1是放行检查的前提。一旦值被压到-1函数直接返回false连默认的原版 StageType 判断都不会执行。即使玩家已经满足进入镜像维度或废弃矿井的全部条件谜题门也不会出现。DEFAULT 0恢复原版行为0是ForceSpecialQuest的默认值对应完全遵循原版逻辑// ForceSpecialQuest 0 defaults to vanilla behavior ret levelASM.ForceSpecialQuest 0 || (g_Game-_stageType 4 || g_Game-_stageType 5);当值为0时ForceSpecialQuest 0为假生成权完全交由原版判定——只有处于STAGETYPE_REPENTANCEStageType 4或STAGETYPE_REPENTANCE_BStageType 5这两种忏悔专属阶段类型时才允许刷门。这也是 docs/docs/Room.md 中TrySpawnSpecialQuestDoor说明里Mirror Mineshaft door 默认仅能在STAGETYPE_REPENTANCE与STAGETYPE_REPENTANCE_B阶段生成的依据。MIRROR 1强制第一块刀片谜题镜像维度MIRROR对应第一块 Knife Piece 谜题进入 Downpour/Dross 的镜像维度Mirror Dimension。设置后本层会自动尝试为对应 LevelStage 放置谜题门。在 docs/docs/Level.md 中GetForceSpecialQuest的说明为If set, the level will automatically attempt to place the Knife Piece puzzle door for this LevelStage.Level:HasMirrorDimension()返回该层是否拥有用于第一块刀片谜题的镜像维度。从实现看repentogon/LuaInterfaces/LuaLevel.cpp 中HOOK_METHOD(Level, HasMirrorDimension, () - bool) { return CheckQuest(this, g_Game-_stage, 2, 1); }即 MIRRORquest 1与关卡阶段expected 2绑定并通过CheckQuest做最终裁决该函数还额外校验难度_difficulty 2、诅咒标志_curses 2等条件见 LuaLevel.cpp。MINESHAFT 2强制第二块刀片谜题废弃矿井MINESHAFT对应第二块 Knife Piece 谜题进入 Mines/Ashpit 的废弃矿井Abandoned Mineshaft。对应实现HOOK_METHOD(Level, HasAbandonedMineshaft, () - bool) { return CheckQuest(this, g_Game-_stage, 4, 2); }MINESHAFTquest 2与关卡阶段expected 4绑定Level:HasAbandonedMineshaft()则用于查询当前层是否已生成废弃矿井房间。状态存储与生命周期ForceSpecialQuest 字段ForceSpecialQuest并非存放在Level对象内部而是 REPENTOGON 自己维护的一个全局状态字段定义在 repentogon/LuaInterfaces/Level.hstruct LevelASM { int ForceSpecialQuest 0; }; extern LevelASM levelASM;该状态的生命周期管理非常关键每次关卡初始化Level::Init时都会先被重置为0DEFAULT见 repentogon/LuaInterfaces/CustomCallbacks.cpp//PRE_LEVEL_INIT Callback (id: 1060 enum pending) HOOK_METHOD(Level, Init, (bool unk) - void) { levelASM.ForceSpecialQuest 0; ... super(unk); }这与 docs/docs/Level.md 中的明确注释完全吻合This is set toSpecialQuest.DEFAULTimmediately before callingMC_PRE_LEVEL_INIT.在触发MC_PRE_LEVEL_INIT回调之前重置为 DEFAULT。因此模组若想对某层强制指定谜题门必须在MC_PRE_LEVEL_INIT回调中设置否则会在游戏完成Level::Init后被覆盖回默认值。这一机制也确保了上一层的强制设置不会泄漏到下一层。相关 Lua API 一览围绕SpecialQuest枚举REPENTOGON 在 Level 与 Room 两个类上暴露了以下 APIAPI所在类说明Level:GetForceSpecialQuest(): SpecialQuestLevel读取当前强制的特殊任务类型Level:SetForceSpecialQuest(Quest: SpecialQuest)Level设置本层应尝试放置的谜题门Level:HasMirrorDimension(): booleanLevel当前层是否有镜像维度第一块刀片Level:HasAbandonedMineshaft(): booleanLevel当前层是否有废弃矿井第二块刀片Room:TrySpawnSpecialQuestDoor(IgnoreStageType false): booleanRoom在原版函数基础上新增了IgnoreStageType参数的修改版函数GetForceSpecialQuest/SetForceSpecialQuest的 Lua 绑定位于 repentogon/LuaInterfaces/LuaLevel.cpp直接读写levelASM.ForceSpecialQuestLUA_FUNCTION(Lua_GetForceSpecialQuest) { lua_pushinteger(L, (int)levelASM.ForceSpecialQuest); return 1; } LUA_FUNCTION(Lua_SetForceSpecialQuest) { levelASM.ForceSpecialQuest (int)luaL_checkinteger(L, 2); return 0; }Room:TrySpawnSpecialQuestDoor则是通过roomASM.ForceSpecialQuestDoor这个布尔标志实现单次强制刷门见 repentogon/LuaInterfaces/Room/Room.h 与 repentogon/LuaInterfaces/Room/LuaRoom.cppLUA_FUNCTION(Lua_RoomTrySpawnSpecialQuestDoor) { Room* room lua::GetLuabridgeUserdataRoom*(L, 1, lua::Metatables::ROOM, lua::metatables::RoomMT); roomASM.ForceSpecialQuestDoor lua::luaL_optboolean(L, 2, false); lua_pushboolean(L, room-TrySpawnSpecialQuestDoor()); return 1; }注意该布尔标志在SpawnSpecialQuestDoorValidStageTypeCheck中被消费后立刻复位roomASM.ForceSpecialQuestDoor false;属于一次性强制不会跨帧残留。底层实现ASM 补丁如何接管谜题门生成REPENTOGON 对原版TrySpawnSpecialQuestDoor的判定进行了汇编级接管入口是 repentogon/Patches/ASMPatches/ASMLevel.cppvoid ASMPatchTrySpawnSpecialQuestDoor() { SigScan scanner(83f90474??83f9050f85????????83fb02); scanner.Scan(); void* addr scanner.GetAddress(); ZHL::Log([REPENTOGON] Patching TrySpawnSpecialQuestDoor at %p\n, addr); ASMPatch::SavedRegisters savedRegisters(ASMPatch::SavedRegisters::Registers::GP_REGISTERS, true); ASMPatch patch; patch.PreserveRegisters(savedRegisters) .AddInternalCall(SpawnSpecialQuestDoorValidStageTypeCheck) .AddBytes(\x84\xC0) // test al, al .RestoreRegisters(savedRegisters) .AddConditionalRelativeJump(ASMPatcher::CondJumps::JNZ, (char*)addr 0xe) .AddRelativeJump((char*)addr 0xb7); sASMPatcher.PatchAt(addr, patch); }该补丁通过特征码signature83f904...定位原版函数在关键分支处插入内部调用SpawnSpecialQuestDoorValidStageTypeCheck用test al, al 条件跳转决定是否走原版后续逻辑。整个补丁在 repentogon/Patches/ASMPatches.cpp 的PatchSpecialQuest()调用链中统一注册。这解释了为什么ForceSpecialQuest能同时影响自动刷门与StageType 合法性判定两处逻辑——它们都汇聚到这同一个校验函数。实战示例控制刀片谜题门示例 1在任意层强制生成镜像维度谜题门local mod RegisterMod(ForceMirrorQuest, 1) mod:AddCallback(ModCallbacks.MC_PRE_LEVEL_INIT, function() -- 每层初始化时强制尝试放置第一块刀片的镜像维度门 Game():GetLevel():SetForceSpecialQuest(SpecialQuest.MIRROR) end)示例 2强制生成废弃矿井谜题门local mod RegisterMod(ForceMineshaftQuest, 1) mod:AddCallback(ModCallbacks.MC_PRE_LEVEL_INIT, function() Game():GetLevel():SetForceSpecialQuest(SpecialQuest.MINESHAFT) end)示例 3彻底禁用谜题门自定义挑战/移除机制local mod RegisterMod(NoKnifeQuest, 1) mod:AddCallback(ModCallbacks.MC_PRE_LEVEL_INIT, function() Game():GetLevel():SetForceSpecialQuest(SpecialQuest.DISABLED) end)示例 4读取当前状态并配合 Room 手动刷门local level Game():GetLevel() local quest level:GetForceSpecialQuest() if quest SpecialQuest.DISABLED then -- 特殊任务门已被禁用 elseif quest SpecialQuest.MIRROR then -- 本层正在尝试镜像维度谜题 end -- 无视 StageType 限制手动强制在当前房间刷出谜题门 -- 注意进入前必须正确设置 KNIFE_PUZZLE 维度否则可能崩溃 Game():GetRoom():TrySpawnSpecialQuestDoor(true)使用注意事项设置时机ForceSpecialQuest在每次Level::Init前被重置为DEFAULT因此强制设置必须放在MC_PRE_LEVEL_INIT回调内执行见 docs/docs/Level.md 与 CustomCallbacks.cpp。维度配套Room:TrySpawnSpecialQuestDoor(true)允许在忏悔阶段之外刷出 Mirror/Mineshaft 门但 docs/docs/Room.md 明确警告KNIFE_PUZZLE维度必须正确设置否则进门会崩溃。该维度与MIRROR、MINESHAFT共享取值1见 docs/docs/enums/Dimension.md。难度限制CheckQuest仅在_difficulty 2即非贪婪模式等情境时生效Greed 模式等场景下强制逻辑不会介入LuaLevel.cpp。功能来源Level:Get/SetForceSpecialQuest是 REPENTOGON 迭代新增的能力changelog.txt 中记录有 Started work on Level:Get/SetForceSpecialQuest见 changelog.txt表明该 API 属于持续演进的扩展功能依赖 REPENTOGON 运行时而非原版引擎。参考资料枚举官方定义docs/docs/enums/SpecialQuest.mdLua 全局表定义repentogon/resources/scripts/enums_ex.luaAPI 文档docs/docs/Level.md、docs/docs/Room.mdLua 绑定实现repentogon/LuaInterfaces/LuaLevel.cpp、repentogon/LuaInterfaces/Room/LuaRoom.cppASM 补丁实现repentogon/Patches/ASMPatches/ASMLevel.cpp状态字段定义repentogon/LuaInterfaces/Level.h、repentogon/LuaInterfaces/Room/Room.h状态重置逻辑repentogon/LuaInterfaces/CustomCallbacks.cpp赞分享游戏开发插件系统【免费下载链接】REPENTOGONScript extender for The Binding of Isaac: Repentance项目地址https://gitcode.com/gh_mirrors/re/REPENTOGON点击查看免费下载相关推荐REPENTOGON WaterClipFlag 枚举完全指南掌控《以撒的结合忏悔》水中渲染与倒影行为REPENTOGON WaterClipFlag 枚举完全指南掌控《以撒的结合忏悔》水中渲染与倒影行为 WaterClipFlag 是 REPENTOGON游戏开发插件系统REPENTOGON DebugFlag 枚举全解析以位掩码控制《以撒的忏悔》调试开关REPENTOGON DebugFlag 枚举全解析以位掩码控制《以撒的忏悔》调试开关 DebugFlag 是 REPENTOGON 为《以撒的结合忏悔》游戏开发插件系统JavaScript 闭包陷阱深度解析为什么 makeArmy 里所有 shooter 都输出 10Modern JavaScript Tutorial 实战篇JavaScript 闭包陷阱深度解析为什么 makeArmy 里所有 shooter 都输出 10Modern JavaScript Tutorial 实游戏开发插件系统上一篇Vega Fold 变换详解将矩阵与交叉表数据重塑为键值对标准格式下一篇探索Octopi一款强大的Pacman/AUR前端工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考