尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
REPENTOGON GridEntityDoor 扩展指南:门对象 PreviousState/PreviousVariant 修复与新 API 实战
游戏开发插件系统【免费下载链接】REPENTOGONScript extender for The Binding of Isaac: Repentance项目地址https://gitcode.com/gh_mirrors/re/REPENTOGON点击查看免费下载本文面向 The Binding of Isaac: Repentance 的模组开发者系统讲解 REPENTOGON 脚本扩展器对GridEntityDoor网格实体门这一 Lua 类所做的全部改动。读完你将掌握PreviousState与PreviousVariant两个由 userdata 修正为整数的读写变量、GetExtraSprite()与PlayAnimation()两个新增函数以及它们背后的源码实现、相关门渲染/更新回调与门槽位DoorSlot/DoorMask联动用法。一、GridEntityDoor 是什么GridEntityDoor是 GridEntity 的派生类对应游戏网格中的门实体房间入口、出口、隐藏门等。在 REPENTOGON 中它被挂接到独立的 Lua metatableGRID_ENTITY_DOOR并在 LuaClasses.h 中通过LuaGridEntityDoor LuabridgeTypeGridEntity_Door, ...导出到 Lua 环境。原版 API 对门的控制能力有限门的关键内部状态变化前的状态暴露给 Lua 时是不透明的 userdata模组无法直接读取或写回同时缺少对附加精灵ExtraSprite与动画播放的原生访问接口。REPENTOGON 在 docs/docs/GridEntityDoor.md 中记录了两类修复Modified Variables修改变量与Functions新增函数。二、PreviousState / PreviousVariant从 userdata 修正为整数这是本文档最重要的改动。原版中GridEntityDoor.PreviousState与PreviousVariant返回的是 userdata指向内部结构模组拿不到可用的数值REPENTOGON 将其修复为返回真正的整数int并且支持读写。变量类型说明PreviousStateint与默认行为相同但现在返回正确的整数值而非 userdataPreviousVariantint与默认行为相同但现在返回正确的整数值而非 userdata重要更新时机根据 docs/docs/GridEntityDoor.md 的注记这两个字段只在初始化门的子类initializing a door subclass或播放动画playing an animation时才会被更新。也就是说门的前一个 State / 前一个 Variant并不在每次状态变更时都刷新模组若依赖这两个字段做状态机判断需要结合门的动画播放时机来理解其语义。底层实现验证修复由 LuaGridEntityDoor.cpp 完成两个RegisterVariable注册了 getter/setter读操作直接lua_pushinteger返回gridEnt-_previousState/gridEnt-_previousVariant均为unsigned int写操作通过luaL_checkinteger接收整数并回写lua::RegisterVariable(_state, lua::Metatables::GRID_ENTITY_DOOR, PreviousState, Lua_GridEntityDoor_GetPreviousState, Lua_GridEntityDoor_SetPreviousState); lua::RegisterVariable(_state, lua::Metatables::GRID_ENTITY_DOOR, PreviousVariant, Lua_GridEntityDoor_GetPreviousVarinat, Lua_GridEntityDoor_SetPreviousVariant);对应的内存布局在 GridEntityDoor.zhl 中定义_previousState位于偏移0x284、_previousVariant位于偏移0x288uint32_t。因为 getter/setter 直通原生字段Lua 侧读写即原生侧读写可用于检测门的类型/变体切换例如普通门与隐藏门之间的形态变化。三、GetExtraSprite()以函数形式访问附加精灵原版门对象持有变量ExtraSprite附加精灵例如门框装饰、谜题门特效但 REPENTOGON 以getter 函数GetExtraSprite()的方式暴露它---return Sprite local sprite door:GetExtraSprite()返回类型为 Sprite。实现上LuaGridEntityDoor.cpp 直接取出结构体偏移0x168处的ANM2 _extraSprite并作为 Sprite userdata 压栈返回因此你可以对返回的 Sprite 继续调用SetFrame、Play、ReplaceSpritesheet等常规 Sprite API实现自定义门的附加贴图与动画。四、PlayAnimation()播放门的动画door:PlayAnimation()该函数没有参数、没有返回值void用于主动播放门对象的动画。LuaGridEntityDoor.cpp 中的实现直接调用原生方法gridEnt-play_animation()LUA_FUNCTION(Lua_GridEntityDoor_PlayAnimation) { GridEntity_Door* gridEnt lua::GetLuabridgeUserdataGridEntity_Door*(L, 1, lua::Metatables::GRID_ENTITY_DOOR, GridEntityDoor); gridEnt-play_animation(); return 0; }play_animation()是游戏原生函数在 GridEntityDoor.zhl 中通过__thiscall签名定位。注意前面提到的PreviousState/PreviousVariant刷新时机之一就是播放动画所以调用PlayAnimation()后这两个字段会被重新计算模组可以在播放前后分别读取借此捕获门动画切换带来的形态变化。五、与门相关的回调GridEntity Door callbacks门是 REPENTOGON 网格渲染/更新回调体系的一等公民。在 CustomCallbacks.cpp 中GridEntity_Door的Render被挂接了HOOK_GRIDRENDER_CALLBACKS对应两个回调 ID在 CustomCallbacks.cpp 中Update被挂接了HOOK_GRIDUPDATE_CALLBACKS回调 ID名称参数返回1446MC_PRE_GRID_ENTITY_DOOR_RENDER(GridEntityDoor Door, Vector Offset)Vector或boolean1447MC_POST_GRID_ENTITY_DOOR_RENDER(GridEntityDoor Door)void1402MC_PRE_GRID_ENTITY_DOOR_UPDATE(GridEntityDoor Door)boolean1403MC_POST_GRID_ENTITY_DOOR_UPDATE(GridEntityDoor Door)void以上参数/返回信息来自 ModCallbacks 枚举文档。PRE 回调返回Vector可改写渲染偏移返回booleanfalse可取消默认渲染UPDATE 的 PRE 回调返回boolean可决定是否跳过原生更新逻辑。示例mod:AddCallback(ModCallbacks.MC_PRE_GRID_ENTITY_DOOR_UPDATE, function(_, door) if door.Variant SomeDoorVariant then return false -- 跳过原生日志执行自定义逻辑 end end)六、结合 DoorSlot / DoorMask 与门放置逻辑的实际应用要写出门相关的模组逻辑通常还需要理解门的槽位概念。门的槽位DoorSlot取值为 0~7左/上/右/下加上第二轮LEFT1/UP1/RIGHT1/DOWN1每个槽位对应一个位掩码定义在 DoorMask 枚举文档中值枚举值枚举1 0LEFT01 4LEFT11 1UP01 5UP11 2RIGHT01 6RIGHT11 3DOWN01 7DOWN1Lua 侧的同名枚举在 enums_ex.lua 中以1 DoorSlot.LEFT0的形式定义。C 侧 RoomPlacement.h 提供了DoorSlotToMask(doorSlot) 1 doorSlot的等价转换。实战把门补进现有房间Level 文档 给出了一段完整可用的示例遍历当前房间 0~7 的每个门槽位用位掩码判断该槽位是否允许放门roomDesc.Data.Doors (1 doorSlot) ~ 0若当前没有门not room:GetDoor(doorSlot)则随机生成一个 1x1 房间并通过TryPlaceRoomAtDoor把连接门补上mod:AddCallback(ModCallbacks.MC_USE_ITEM, function(_, id, rng, player, flags, slot) local level game:GetLevel() local room game:GetRoom() local roomDesc level:GetCurrentRoomDesc() local success false for doorSlot 0, 7 do local doorSlotAllowed roomDesc.Data.Doors (1 doorSlot) ~ 0 if doorSlotAllowed and not room:GetDoor(doorSlot) then local seed rng:Next() local requiredDoors 15 -- 要求新房间 4 个槽位都有门确保放得下 local roomConfig RoomConfig.GetRandomRoom(seed, true, Isaac.GetCurrentStageConfigId(), RoomType.ROOM_DEFAULT, RoomShape.ROOMSHAPE_1x1, nil, nil, nil, nil, requiredDoors) if roomConfig then local newRoom level:TryPlaceRoomAtDoor(roomConfig, roomDesc, doorSlot, seed, true, false) if newRoom then success true end end end end if success then return {ShowAnim true} else return {Discharge false} end end, MY_ACTIVE_ITEM_ID)这段代码在门生成成功后返回{ShowAnimtrue}播放门的动画——恰好对应本文第四节PlayAnimation()所触发的原生动画路径。底层门是如何被实体化的从源码结构可以推断门的生成由房间放置系统驱动。在 RoomPlacement.cpp 中当新房间与玩家当前房间相邻时通过currentRoom-MakeDoor(returnDoorSlot)创建门实体随后写入目标房间索引door-_targetRoomIdx、调用SetRoomTypes(CurrentRoomType, TargetRoomType)设置两侧房间类型并在房间帧数大于 0 时调用door-play_animation()播放开门动画currentRoom-MakeDoor(returnDoorSlot); GridEntity_Door* door currentRoom-GetDoor(returnDoorSlot); if (door) { door-_targetRoomIdx roomDesc-SafeGridIndex; door-SetRoomTypes(neighborDesc-Data-Type, roomDesc-Data-Type); if (currentRoom-GetFrameCount() 0) { door-play_animation(); } }GetDoor(slot)的原生签名__thiscall GridEntity_Door* Room::GetDoor(int slot)定义在 Room.zhl 中这与上面 Lua 示例里的room:GetDoor(doorSlot)一一对应。从这段实现可以看出SetRoomTypes与play_animation是门实例化过程中的关键步骤而_previousState/_previousVariant正是在这类初始化与动画播放的路径上被刷新。七、使用注意事项小结类型语义PreviousState/PreviousVariant现在是int不要再对它们做 userdata 解包setter 仅接受整数。更新时机这两个字段只在门子类初始化或播放动画时更新跨帧持续读取时值可能不变不应将其当作实时状态量。ExtraSprite 是共享引用GetExtraSprite()返回的是门对象内部的ANM2 _extraSprite引用偏移0x168修改它会直接影响门自身的附加精灵渲染谨慎用于全局替换。回调与放置联动门的渲染/更新回调1446/1447、1402/1403与DoorMask位掩码、TryPlaceRoomAtDoor等放置 API 配合使用可以做出动态开新门自定义门动画门不可见/不可通行等玩法效果。参考路径汇总类文档docs/docs/GridEntityDoor.md门枚举docs/docs/enums/DoorMask.md回调枚举docs/docs/enums/ModCallbacks.md门 Lua 绑定实现repentogon/LuaInterfaces/GridEntities/LuaGridEntityDoor.cpp门原生结构体与函数定位libzhl/functions/GridEntityDoor.zhl门渲染/更新回调挂接repentogon/LuaInterfaces/CustomCallbacks.cpp房间门生成逻辑repentogon/LuaInterfaces/Room/RoomPlacement.cppLua 侧 DoorMask 枚举repentogon/resources/scripts/enums_ex.lua赞分享游戏开发插件系统【免费下载链接】REPENTOGONScript extender for The Binding of Isaac: Repentance项目地址https://gitcode.com/gh_mirrors/re/REPENTOGON点击查看免费下载相关推荐REPENTOGON 扩展 API 实战指南EntityBomb 炸弹实体类完整解析REPENTOGON 扩展 API 实战指南EntityBomb 炸弹实体类完整解析 导读 本文聚焦 REPENTOGON 为《以撒的结合忏悔》Lua Mo游戏开发插件系统REPENTOGON Lua API 扩展全览800 新函数、200 新回调与 60 新枚举的文档导航与实践指南REPENTOGON Lua API 扩展全览800 新函数、200 新回调与 60 新枚举的文档导航与实践指南 本文面向《以撒的结合忏悔》The游戏开发插件系统如何 5 分钟给小爱音箱免费装上无限曲库XiaoMusic Docker 部署与语音点播指南如何 5 分钟给小爱音箱免费装上无限曲库XiaoMusic Docker 部署与语音点播指南 XiaoMusic 是一款开源音乐工具它接管小爱音箱的语音点播游戏开发插件系统上一篇Sunshine打造个人游戏串流服务器的终极指南下一篇Sunshine游戏串流完整指南5分钟搭建免费个人云游戏平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

技术创业路径拆解:从实验室到上市公司的关键阶段与避坑指南

技术创业路径拆解:从实验室到上市公司的关键阶段与避坑指南

“3位清华同学港股敲锣了”,最近在技术圈里刷屏。很多讨论把注意力放在“名校、年轻、财富”这些标签上,但作为一名开发者,我看到的不是钟声,而是另一件事:三位技术背景的创始人,把一家公司从代码做到了港股…

📅 2026/10/16 2:21:32
OpenClaw `openclaw onboard` 命令完全指南:交互式引导配置 Gateway、工作区、认证与渠道

OpenClaw `openclaw onboard` 命令完全指南:交互式引导配置 Gateway、工作区、认证与渠道

人工智能大模型LLM 网关AI Agent即时通讯 【免费下载链接】openclaw-zero-token OpenClaw: Use All Major AI Models NO API Token! Claude/ChatGPT/Gemini/DeepSeek/Doubao/Grok/Qwen/Manus/Kimi 项目地址: https://gitcode.com/gh_mirrors/op/openclaw-zero-token…

📅 2026/10/16 2:21:32
LangChain入门---基于DeepSeek-V4-Pro模型

LangChain入门---基于DeepSeek-V4-Pro模型

一.LangChain基础概念1.什么是LLM大语言模型(LLM)是基于海量文本训练的深度学习模型,能够理解和生成自然语言。其核心是通过Transformer架构捕捉上下文依赖关系,实现文本生成、问答、翻译等任务。典型代表如GPT-4、Claude、DeepSe…

📅 2026/10/16 2:21:32
MORE NEWS

更多资讯

📰

AI生成教材如何降低查重率?从根因到参数调优的完整方案

当AI开始承担教材初稿的撰写,最先撞上的往往不是写作能力,而是查重率这个硬指标。不少用AI生成教材的朋友都有过这种经历:明明每句话读起来通顺正常,丢进查重系统一跑,重复率直奔三四十甚至更高。这里要明确一个前提&a…

📰

设备保养不是换油擦灰,做到真正有效还差这4步

设备保养最让人头疼的是什么? 不是没人干,而是保养天天做,设备照样坏。 润滑油按时换了,设备表面擦干净了,螺丝也拧紧了,保养记录一张没少。结果没过几天,轴承又发热、皮带又打滑,同…

📰

数据结构的基础笔记

文章目录1.数据排序1.1 简单排序1.2.1 冒泡排序1.2.2选择排序1.2.3插入排序1.2高级排序1.2.1希尔排序1.2.2归并排序1.2.2.1 递归快速排序1.数据排序 1.1 简单排序 Comparable接口 1.2.1 冒泡排序 是一种稳定排序方法! 1.比较相邻的元素。如果前一个元素比后一个元素大&…

📰

C++模板元编程:编译期类型计算与零开销抽象实战

1. 这不是“写代码”,是在编译期“造机器”——C模板元编程到底在干什么?很多人第一次听说“C模板元编程”,脑子里浮现的可能是“晦涩”“难懂”“只有编译器开发者才碰的东西”。但事实恰恰相反:它早已悄悄跑在你每天用的std::ve…

📰

Spring Boot 3.5.16 自带的 Tomcat 10.1.55 中了哪些 CVE?其中一条是修上一个漏洞时带进来的

文中的数字都是 2026-10-13 读到的。GitHub 的审核状态和 Spring Boot 的版本会变,结论请以你看到这篇文章当天的实际情况为准。 先说结论 Tomcat 官方在 2026 年 8 月和 9 月各修了一批漏洞,共 22 条: 批次条数修复版8 月批109.0.121 / 10.1.58 / 11.0.259 月批(官方写 2026…

📰

MCP实战手记(十一):MCP接飞书,从机器人到事件订阅的三层深度接入

本文聚焦飞书三层接入(机器人Webhook/自建应用卡片/长连接事件订阅)钉钉横向对比。0. 开篇:为什么从飞书开始 CSDN上"飞书对接"的实战文不少,但"飞书长连接事件订阅MCP双向闭环"的完整跑通几乎空白。飞书开放…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬