From 8b175214f88ec9b4ecd45c36944fc198b622db89 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sun, 2 Nov 2025 21:23:24 +0100 Subject: [PATCH 01/35] Reset room list function --- libzhl/functions/Level.zhl | 3 +++ repentogon/LuaInterfaces/LuaLevel.cpp | 25 ++++++++++++++++++++++ repentogon/Patches/ASMPatches/ASMLevel.cpp | 23 ++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/libzhl/functions/Level.zhl b/libzhl/functions/Level.zhl index 93bfc950a..b066b52d5 100644 --- a/libzhl/functions/Level.zhl +++ b/libzhl/functions/Level.zhl @@ -7,6 +7,9 @@ __thiscall void Level::Init(bool unkinitStartRoom); "518b89????????e8": __thiscall void Level::Update(); +"558bec6aff68????????64a1????????5081ecc0000000a1????????33c58945??535657508d45??64a3????????8bc1": +__thiscall void Level::reset_room_list(int param_1); + "558bec6aff68????????64a1????????5083ec2c535657a1????????33c5508d45??64a3????????8bd98b45": __thiscall void Level::ChangeRoom(int targetRoomIDX, int dimension); diff --git a/repentogon/LuaInterfaces/LuaLevel.cpp b/repentogon/LuaInterfaces/LuaLevel.cpp index 419fc642f..c16926f45 100644 --- a/repentogon/LuaInterfaces/LuaLevel.cpp +++ b/repentogon/LuaInterfaces/LuaLevel.cpp @@ -40,6 +40,28 @@ LUA_FUNCTION(Lua_LevelHasPhotoDoor) return 1; } +LUA_FUNCTION(lua_LevelResetRoomList) { + Level* level = lua::GetLuabridgeUserdata(L, 1, lua::Metatables::LEVEL, "Level"); + level->reset_room_list(1); + + // Clean up the room list + for (size_t i = 0; i < 507; i++) + { + g_Game->_roomOffset[i] = -1; + } + + // Clean up the number of rooms + g_Game->_nbRooms = 0; + + return 0; +} + +LUA_FUNCTION(lua_LevelSetLastBossRoomListIndex) { + int listIndex = (int)luaL_checkinteger(L, 2); + g_Game->_lastBossRoomListIdx = listIndex; + return 1; +} + static std::string CustomStageName; LUA_FUNCTION(lua_LevelSetName) { @@ -372,6 +394,9 @@ HOOK_METHOD(LuaEngine, RegisterClasses, () -> void) { { "GetNeighboringRooms", Lua_LevelGetNeighboringRooms }, { "GetGenerationRNG", Lua_LevelGetGenerationRNG }, + { "ResetRoomList", lua_LevelResetRoomList }, + { "SetLastBossRoomListIndex", lua_LevelSetLastBossRoomListIndex }, + { NULL, NULL } }; diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index 34d51aeb5..1c7c838ec 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -84,6 +84,23 @@ void ASMPatchVoidGeneration() { HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { + const int callbackId = 1193; + if (CallbackState.test(callbackId - 1000)) { + lua_State* L = g_LuaEngine->_state; + lua::LuaStackProtector protector(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); + + lua::LuaResults results = lua::LuaCaller(L).push(callbackId).call(1); + + if (!results) { + if (lua_isboolean(L, -1)) { + if (lua_toboolean(L, -1)) { + return; + } + } + } + } + if (this->_stage == 12) { if (generateLevels.any()) @@ -117,6 +134,12 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) super(rng); } +//HOOK_METHOD(Level, reset_room_list, (int a) -> void) +//{ +// KAGE::_LogMessage(0, "[SEX] Weird value: %d.\n", a); +// super(a); +//} + bool __stdcall SpawnSpecialQuestDoorValidStageTypeCheck() { // Always return true if we forced it via Room:TrySpawnSpecialQuestDoor bool ret = roomASM.ForceSpecialQuestDoor; From 7c047e1564ef597d24ae83398996589f98a2ff60 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sun, 2 Nov 2025 21:53:48 +0100 Subject: [PATCH 02/35] Added bool parameter --- libzhl/functions/Level.zhl | 2 +- repentogon/LuaInterfaces/LuaLevel.cpp | 4 +++- repentogon/Patches/ASMPatches/ASMLevel.cpp | 6 ------ 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/libzhl/functions/Level.zhl b/libzhl/functions/Level.zhl index b066b52d5..d711d9c39 100644 --- a/libzhl/functions/Level.zhl +++ b/libzhl/functions/Level.zhl @@ -8,7 +8,7 @@ __thiscall void Level::Init(bool unkinitStartRoom); __thiscall void Level::Update(); "558bec6aff68????????64a1????????5081ecc0000000a1????????33c58945??535657508d45??64a3????????8bc1": -__thiscall void Level::reset_room_list(int param_1); +__thiscall void Level::reset_room_list(bool unkinitStartRoom); "558bec6aff68????????64a1????????5083ec2c535657a1????????33c5508d45??64a3????????8bd98b45": __thiscall void Level::ChangeRoom(int targetRoomIDX, int dimension); diff --git a/repentogon/LuaInterfaces/LuaLevel.cpp b/repentogon/LuaInterfaces/LuaLevel.cpp index c16926f45..5f23db5da 100644 --- a/repentogon/LuaInterfaces/LuaLevel.cpp +++ b/repentogon/LuaInterfaces/LuaLevel.cpp @@ -41,8 +41,10 @@ LUA_FUNCTION(Lua_LevelHasPhotoDoor) } LUA_FUNCTION(lua_LevelResetRoomList) { + bool unkInitFirstRoom = (bool)lua::luaL_checkboolean(L, 2); + Level* level = lua::GetLuabridgeUserdata(L, 1, lua::Metatables::LEVEL, "Level"); - level->reset_room_list(1); + level->reset_room_list(unkInitFirstRoom); // Clean up the room list for (size_t i = 0; i < 507; i++) diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index 1c7c838ec..5324e0391 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -134,12 +134,6 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) super(rng); } -//HOOK_METHOD(Level, reset_room_list, (int a) -> void) -//{ -// KAGE::_LogMessage(0, "[SEX] Weird value: %d.\n", a); -// super(a); -//} - bool __stdcall SpawnSpecialQuestDoorValidStageTypeCheck() { // Always return true if we forced it via Room:TrySpawnSpecialQuestDoor bool ret = roomASM.ForceSpecialQuestDoor; From ea8320ceb8611375595cc6c09a0e4a324469fa26 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sun, 2 Nov 2025 22:02:46 +0100 Subject: [PATCH 03/35] Added callback enum --- repentogon/Patches/ASMPatches/ASMLevel.cpp | 2 +- repentogon/resources/scripts/enums_ex.lua | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index 5324e0391..dbc78180d 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -84,7 +84,7 @@ void ASMPatchVoidGeneration() { HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { - const int callbackId = 1193; + const int callbackId = 1340; if (CallbackState.test(callbackId - 1000)) { lua_State* L = g_LuaEngine->_state; lua::LuaStackProtector protector(L); diff --git a/repentogon/resources/scripts/enums_ex.lua b/repentogon/resources/scripts/enums_ex.lua index c63e47ced..7a879fa79 100644 --- a/repentogon/resources/scripts/enums_ex.lua +++ b/repentogon/resources/scripts/enums_ex.lua @@ -266,6 +266,8 @@ ModCallbacks.MC_PRE_PICKUP_UPDATE_GHOST_PICKUPS = 1335 --ModCallbacks.MC_PRE_NPC_GET_LOOT_LIST = 1336 (Reserved for the future) --ModCallbacks.MC_PRE_NPC_UPDATE_GHOST_PICKUPS = 1337 (Reserved for the future) +ModCallbacks.MC_PRE_GENERATE_DUNGEON = 1340 + ModCallbacks.MC_PRE_PLAYER_ADD_CARD = 1350 ModCallbacks.MC_POST_PLAYER_ADD_CARD = 1351 ModCallbacks.MC_PRE_PLAYER_ADD_PILL = 1352 From 2490b78c8b95e97ce2e5fedddc394a8c0ddff055 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Mon, 3 Nov 2025 12:27:34 +0100 Subject: [PATCH 04/35] Added RNG parameter to callback --- repentogon/Patches/ASMPatches/ASMLevel.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index dbc78180d..a7707ea99 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -82,6 +82,7 @@ void ASMPatchVoidGeneration() { sASMPatcher.PatchAt(addr, &patch); } +//MC_PRE_GENERATE_DUNGEON(1340) HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { const int callbackId = 1340; @@ -90,7 +91,11 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) lua::LuaStackProtector protector(L); lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - lua::LuaResults results = lua::LuaCaller(L).push(callbackId).call(1); + lua::LuaResults results = lua::LuaCaller(L) + .push(callbackId) + .pushnil() + .push(rng, lua::Metatables::RNG) + .call(1); if (!results) { if (lua_isboolean(L, -1)) { From 8f8c1575d977a18d0efd5499154c7d3b89589eae Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Tue, 4 Nov 2025 18:43:09 +0100 Subject: [PATCH 05/35] Added dungeon generator controller --- libzhl/LuaCore.cpp | 1 + libzhl/LuaCore.h | 1 + .../LuaInterfaces/LuaDungeonGenerator.cpp | 69 +++++++++++++++++++ .../LuaInterfaces/LuaDungeonGenerator.h | 34 +++++++++ repentogon/LuaInterfaces/LuaLevel.cpp | 27 -------- repentogon/Patches/ASMPatches/ASMLevel.cpp | 48 +++++++++++-- 6 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 repentogon/LuaInterfaces/LuaDungeonGenerator.cpp create mode 100644 repentogon/LuaInterfaces/LuaDungeonGenerator.h diff --git a/libzhl/LuaCore.cpp b/libzhl/LuaCore.cpp index c746d3fe8..9aace6ca4 100644 --- a/libzhl/LuaCore.cpp +++ b/libzhl/LuaCore.cpp @@ -838,6 +838,7 @@ namespace lua { const char* LootListEntryMT = "LootListEntry"; const char* MinimapConfigMT = "MinimapConfig"; const char* EntityDescMT = "EntityDesc"; + const char* DungeonGeneratorMT = "DungeonGenerator"; } void TableAssoc(lua_State* L, std::string const& name, int value) { diff --git a/libzhl/LuaCore.h b/libzhl/LuaCore.h index 9d1ef9685..187208bf6 100644 --- a/libzhl/LuaCore.h +++ b/libzhl/LuaCore.h @@ -257,6 +257,7 @@ namespace lua { extern LIBZHL_API const char* LootListEntryMT; extern LIBZHL_API const char* MinimapConfigMT; extern LIBZHL_API const char* EntityDescMT; + extern LIBZHL_API const char* DungeonGeneratorMT; } LIBZHL_API void UnloadMetatables(); diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp new file mode 100644 index 000000000..c3840b4eb --- /dev/null +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -0,0 +1,69 @@ +#include "HookSystem.h" +#include "IsaacRepentance.h" +#include "LuaCore.h" +#include "Exception.h" +#include "Log.h" +#include "LuaDungeonGenerator.h" + +DungeonGenerator* GetDungeonGenerator(lua_State* L) { + return *lua::GetRawUserdata(L, 1, lua::metatables::DungeonGeneratorMT); +} + +LUA_FUNCTION(test) { + DungeonGenerator* generator = GetDungeonGenerator(L); + generator->a++; + KAGE::_LogMessage(0, "[SEX] Test function \n"); + return 1; +} + +LUA_FUNCTION(place_room) { + DungeonGenerator* generator = GetDungeonGenerator(L); + RoomConfig_Room* config = lua::GetLuabridgeUserdata(L, 2, lua::Metatables::CONST_ROOM_CONFIG_ROOM, "RoomConfig"); + uint32_t row = (uint32_t)luaL_checkinteger(L, 3); + uint32_t col = (uint32_t)luaL_checkinteger(L, 4); + uint32_t seed = (uint32_t)luaL_checkinteger(L, 5); + + DungeonGeneratorRoom* generatorRoom = new DungeonGeneratorRoom(config, row, col, seed); + generator->rooms[generator->num_rooms] = *generatorRoom; + + generator->num_rooms++; + + return 1; +} + +LUA_FUNCTION(set_final_boss_room) { + DungeonGenerator* generator = GetDungeonGenerator(L); + uint32_t row = (uint32_t)luaL_checkinteger(L, 2); + uint32_t col = (uint32_t)luaL_checkinteger(L, 3); + + for (size_t i = 0; i < 169; i++) { + DungeonGeneratorRoom generatorRoom = generator->rooms[i]; + + if (generatorRoom.room != NULL) { + if (row == generatorRoom.row && col == generatorRoom.col) { + generatorRoom.is_final_boss = true; + break; + } + } else { + break; + } + } + + return 1; +} + +static void RegisterDungeonGenerator(lua_State* L) { + luaL_Reg functions[] = { + {"Test", test}, + {"PlaceRoom", place_room}, + {"SetFinalBossRoom", set_final_boss_room}, + { NULL, NULL } + }; + + lua::RegisterNewClass(L, lua::metatables::DungeonGeneratorMT, lua::metatables::DungeonGeneratorMT, functions); +} + +HOOK_METHOD(LuaEngine, RegisterClasses, () -> void) { + super(); + RegisterDungeonGenerator(_state); +} \ No newline at end of file diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h new file mode 100644 index 000000000..d6c914d3b --- /dev/null +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -0,0 +1,34 @@ +#pragma once + +struct DungeonGeneratorRoom { + RoomConfig_Room* room; + uint32_t row; + uint32_t col; + uint32_t seed; + bool is_final_boss = false; + + DungeonGeneratorRoom() { + this->room = NULL; + this->row = -1; + this->col = -1; + this->seed = -1; + } + + DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col, uint32_t seed) { + this->room = room; + this->row = row; + this->col = col; + this->seed = seed; + } +}; + +struct DungeonGenerator { + int a; + int num_rooms; + DungeonGeneratorRoom rooms[169]; + + DungeonGenerator() { + a = 0; + num_rooms = 0; + } +}; \ No newline at end of file diff --git a/repentogon/LuaInterfaces/LuaLevel.cpp b/repentogon/LuaInterfaces/LuaLevel.cpp index 5f23db5da..419fc642f 100644 --- a/repentogon/LuaInterfaces/LuaLevel.cpp +++ b/repentogon/LuaInterfaces/LuaLevel.cpp @@ -40,30 +40,6 @@ LUA_FUNCTION(Lua_LevelHasPhotoDoor) return 1; } -LUA_FUNCTION(lua_LevelResetRoomList) { - bool unkInitFirstRoom = (bool)lua::luaL_checkboolean(L, 2); - - Level* level = lua::GetLuabridgeUserdata(L, 1, lua::Metatables::LEVEL, "Level"); - level->reset_room_list(unkInitFirstRoom); - - // Clean up the room list - for (size_t i = 0; i < 507; i++) - { - g_Game->_roomOffset[i] = -1; - } - - // Clean up the number of rooms - g_Game->_nbRooms = 0; - - return 0; -} - -LUA_FUNCTION(lua_LevelSetLastBossRoomListIndex) { - int listIndex = (int)luaL_checkinteger(L, 2); - g_Game->_lastBossRoomListIdx = listIndex; - return 1; -} - static std::string CustomStageName; LUA_FUNCTION(lua_LevelSetName) { @@ -396,9 +372,6 @@ HOOK_METHOD(LuaEngine, RegisterClasses, () -> void) { { "GetNeighboringRooms", Lua_LevelGetNeighboringRooms }, { "GetGenerationRNG", Lua_LevelGetGenerationRNG }, - { "ResetRoomList", lua_LevelResetRoomList }, - { "SetLastBossRoomListIndex", lua_LevelSetLastBossRoomListIndex }, - { NULL, NULL } }; diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index a7707ea99..caedd4b13 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -5,6 +5,7 @@ #include "ASMLevel.h" #include "../../LuaInterfaces/Level.h" #include "../../LuaInterfaces/Room/Room.h" +#include "../../LuaInterfaces/LuaDungeonGenerator.h" std::bitset<36> generateLevels; @@ -86,20 +87,59 @@ void ASMPatchVoidGeneration() { HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { const int callbackId = 1340; - if (CallbackState.test(callbackId - 1000)) { + if (CallbackState.test(callbackId - 1000)) + { lua_State* L = g_LuaEngine->_state; lua::LuaStackProtector protector(L); lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); + DungeonGenerator generator = {}; + KAGE::_LogMessage(0, "[SEX] Before callback: %d \n", generator.a); + lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) .pushnil() .push(rng, lua::Metatables::RNG) + .push(&generator, lua::metatables::DungeonGeneratorMT) .call(1); - if (!results) { - if (lua_isboolean(L, -1)) { - if (lua_toboolean(L, -1)) { + KAGE::_LogMessage(0, "[SEX] After callback: %d \n", generator.a); + + if (!results) + { + if (lua_isboolean(L, -1)) + { + if (lua_toboolean(L, -1)) + { + this->reset_room_list(false); + + // Clean up the room list + for (size_t i = 0; i < 507; i++) + { + g_Game->_roomOffset[i] = -1; + } + + // Clean up the number of rooms + g_Game->_nbRooms = 0; + + for (size_t i = 0; i < 169; i++) + { + DungeonGeneratorRoom generator_room = generator.rooms[i]; + + if (generator_room.room != NULL) { + LevelGenerator_Room* level_generator_room = new LevelGenerator_Room(); + level_generator_room->_gridColIdx = generator_room.col; + level_generator_room->_gridLineIdx = generator_room.row; + level_generator_room->_doors = 15; + + g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); + + if (generator_room.is_final_boss) { + g_Game->_lastBossRoomListIdx = i; + } + } + } + return; } } From f9fb0199702052516d4f1160b89c4fb6d8af5636 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Tue, 4 Nov 2025 19:04:11 +0100 Subject: [PATCH 06/35] Removed test functions and fixed final boss not set --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 21 +++++++------------ repentogon/Patches/ASMPatches/ASMLevel.cpp | 15 +++++++------ 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index c3840b4eb..1e7da8f8e 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -9,13 +9,6 @@ DungeonGenerator* GetDungeonGenerator(lua_State* L) { return *lua::GetRawUserdata(L, 1, lua::metatables::DungeonGeneratorMT); } -LUA_FUNCTION(test) { - DungeonGenerator* generator = GetDungeonGenerator(L); - generator->a++; - KAGE::_LogMessage(0, "[SEX] Test function \n"); - return 1; -} - LUA_FUNCTION(place_room) { DungeonGenerator* generator = GetDungeonGenerator(L); RoomConfig_Room* config = lua::GetLuabridgeUserdata(L, 2, lua::Metatables::CONST_ROOM_CONFIG_ROOM, "RoomConfig"); @@ -36,13 +29,14 @@ LUA_FUNCTION(set_final_boss_room) { uint32_t row = (uint32_t)luaL_checkinteger(L, 2); uint32_t col = (uint32_t)luaL_checkinteger(L, 3); - for (size_t i = 0; i < 169; i++) { - DungeonGeneratorRoom generatorRoom = generator->rooms[i]; + for (size_t i = 0; i < generator->num_rooms; i++) { + DungeonGeneratorRoom* generator_room = &(generator->rooms[i]); - if (generatorRoom.room != NULL) { - if (row == generatorRoom.row && col == generatorRoom.col) { - generatorRoom.is_final_boss = true; - break; + if (generator_room->room != NULL) { + if (row == generator_room->row && col == generator_room->col) { + generator_room->is_final_boss = true; + } else { + generator_room->is_final_boss = false; } } else { break; @@ -54,7 +48,6 @@ LUA_FUNCTION(set_final_boss_room) { static void RegisterDungeonGenerator(lua_State* L) { luaL_Reg functions[] = { - {"Test", test}, {"PlaceRoom", place_room}, {"SetFinalBossRoom", set_final_boss_room}, { NULL, NULL } diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index caedd4b13..1065f0232 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -93,18 +93,14 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) lua::LuaStackProtector protector(L); lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - DungeonGenerator generator = {}; - KAGE::_LogMessage(0, "[SEX] Before callback: %d \n", generator.a); - + DungeonGenerator* generator = new DungeonGenerator(); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) .pushnil() .push(rng, lua::Metatables::RNG) - .push(&generator, lua::metatables::DungeonGeneratorMT) + .push(generator, lua::metatables::DungeonGeneratorMT) .call(1); - KAGE::_LogMessage(0, "[SEX] After callback: %d \n", generator.a); - if (!results) { if (lua_isboolean(L, -1)) @@ -122,9 +118,9 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) // Clean up the number of rooms g_Game->_nbRooms = 0; - for (size_t i = 0; i < 169; i++) + for (size_t i = 0; i < generator->num_rooms; i++) { - DungeonGeneratorRoom generator_room = generator.rooms[i]; + DungeonGeneratorRoom generator_room = generator->rooms[i]; if (generator_room.room != NULL) { LevelGenerator_Room* level_generator_room = new LevelGenerator_Room(); @@ -135,7 +131,10 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); if (generator_room.is_final_boss) { + KAGE::_LogMessage(0, "[SEX] Setting boss room %d\n", i); g_Game->_lastBossRoomListIdx = i; + } else { + KAGE::_LogMessage(0, "[SEX] Not Setting boss room %d\n", i); } } } From f65b5f587ce62ef8e9754e67f9c45b452c8d63ce Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Tue, 4 Nov 2025 20:08:29 +0100 Subject: [PATCH 07/35] Callback triggers for more dungeon types --- libzhl/functions/Level.zhl | 15 ++ repentogon/Patches/ASMPatches/ASMLevel.cpp | 154 +++++++++++++-------- 2 files changed, 114 insertions(+), 55 deletions(-) diff --git a/libzhl/functions/Level.zhl b/libzhl/functions/Level.zhl index d711d9c39..f86d0be4a 100644 --- a/libzhl/functions/Level.zhl +++ b/libzhl/functions/Level.zhl @@ -64,6 +64,21 @@ __thiscall int Level::GetRandomRoomIndex(bool IAmErrorRoom, unsigned int Seed); "538bdc83ec0883e4f883c404558b6b??896c24??8bec6aff68????????64a1????????505381ec50040000": __thiscall void Level::generate_dungeon(RNG * RNG); +"558bec6aff68????????64a1????????5081ecd4030000a1????????33c58945??535657508d45??64a3????????8bd9": +__thiscall void Level::generate_home_dungeon(); + +"538bdc83ec0883e4f883c404558b6b??896c24??8bec6aff68????????64a1????????505381ec30040000": +__thiscall void Level::generate_backwards_dungeon(); + +"558bec6aff68????????64a1????????5081ecc4030000": +__thiscall void Level::generate_redkey_dungeon(); + +"558bec6aff68????????64a1????????5081ecdc030000": +__thiscall void Level::generate_blue_womb(); + +"558bec6aff68????????64a1????????5081ecec030000": +__thiscall void Level::generate_greed_dungeon(); + "558bec6aff68????????64a1????????5083ec68a1????????33c58945??535657508d45??64a3????????8bd98b55": __thiscall bool Level::place_rooms_backwards(LevelGenerator* levelGen, BackwardsStageDesc* backwardsStage, uint32_t stage, uint32_t minDifficulty, uint32_t maxDifficulty); diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index 1065f0232..025197ed2 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -84,67 +84,66 @@ void ASMPatchVoidGeneration() { } //MC_PRE_GENERATE_DUNGEON(1340) -HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) -{ +bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { const int callbackId = 1340; - if (CallbackState.test(callbackId - 1000)) + if (!CallbackState.test(callbackId - 1000)) { + return false; + } + + lua_State* L = g_LuaEngine->_state; + lua::LuaStackProtector protector(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); + + DungeonGenerator* generator = new DungeonGenerator(); + lua::LuaResults results = lua::LuaCaller(L) + .push(callbackId) + .pushnil() + .push(generator, lua::metatables::DungeonGeneratorMT) + .push(rng, lua::Metatables::RNG) + .call(1); + + if (results || !lua_isboolean(L, -1) || !lua_toboolean(L, -1)) { - lua_State* L = g_LuaEngine->_state; - lua::LuaStackProtector protector(L); - lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - - DungeonGenerator* generator = new DungeonGenerator(); - lua::LuaResults results = lua::LuaCaller(L) - .push(callbackId) - .pushnil() - .push(rng, lua::Metatables::RNG) - .push(generator, lua::metatables::DungeonGeneratorMT) - .call(1); - - if (!results) - { - if (lua_isboolean(L, -1)) - { - if (lua_toboolean(L, -1)) - { - this->reset_room_list(false); - - // Clean up the room list - for (size_t i = 0; i < 507; i++) - { - g_Game->_roomOffset[i] = -1; - } - - // Clean up the number of rooms - g_Game->_nbRooms = 0; - - for (size_t i = 0; i < generator->num_rooms; i++) - { - DungeonGeneratorRoom generator_room = generator->rooms[i]; - - if (generator_room.room != NULL) { - LevelGenerator_Room* level_generator_room = new LevelGenerator_Room(); - level_generator_room->_gridColIdx = generator_room.col; - level_generator_room->_gridLineIdx = generator_room.row; - level_generator_room->_doors = 15; - - g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); - - if (generator_room.is_final_boss) { - KAGE::_LogMessage(0, "[SEX] Setting boss room %d\n", i); - g_Game->_lastBossRoomListIdx = i; - } else { - KAGE::_LogMessage(0, "[SEX] Not Setting boss room %d\n", i); - } - } - } - - return; - } + return false; + } + + level->reset_room_list(false); + + for (size_t i = 0; i < 507; i++) + { + g_Game->_roomOffset[i] = -1; + } + + g_Game->_nbRooms = 0; + + for (size_t i = 0; i < generator->num_rooms; i++) + { + DungeonGeneratorRoom generator_room = generator->rooms[i]; + + if (generator_room.room != NULL) { + LevelGenerator_Room* level_generator_room = new LevelGenerator_Room(); + level_generator_room->_gridColIdx = generator_room.col; + level_generator_room->_gridLineIdx = generator_room.row; + level_generator_room->_doors = 15; + + g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); + + if (generator_room.is_final_boss) { + g_Game->_lastBossRoomListIdx = i; } } } + return true; +} + +HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) +{ + bool skip = ProcessGenerateDungeonCallback(this, rng, 1); + if (skip) { + return; + } + if (this->_stage == 12) { if (generateLevels.any()) @@ -178,6 +177,51 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) super(rng); } +HOOK_METHOD(Level, generate_home_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 2); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_blue_womb, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 3); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 4); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 5); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_greed_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 6); + if (skip) { + return; + } + + super(); +} + bool __stdcall SpawnSpecialQuestDoorValidStageTypeCheck() { // Always return true if we forced it via Room:TrySpawnSpecialQuestDoor bool ret = roomASM.ForceSpecialQuestDoor; From d313242b8eb462a4f6fe5bc9bf9e2320a116b67b Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Tue, 4 Nov 2025 20:28:13 +0100 Subject: [PATCH 08/35] Filter by generation type --- repentogon/Patches/ASMPatches/ASMLevel.cpp | 24 +++++++++++----------- repentogon/resources/scripts/enums_ex.lua | 8 ++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index 025197ed2..a9cb5f8ef 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -97,7 +97,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { DungeonGenerator* generator = new DungeonGenerator(); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) - .pushnil() + .push(dungeonType) .push(generator, lua::metatables::DungeonGeneratorMT) .push(rng, lua::Metatables::RNG) .call(1); @@ -139,7 +139,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { - bool skip = ProcessGenerateDungeonCallback(this, rng, 1); + bool skip = ProcessGenerateDungeonCallback(this, rng, 0); if (skip) { return; } @@ -177,17 +177,17 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) super(rng); } -HOOK_METHOD(Level, generate_home_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 2); +HOOK_METHOD(Level, generate_blue_womb, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 1); if (skip) { return; } - + super(); } -HOOK_METHOD(Level, generate_blue_womb, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 3); +HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 2); if (skip) { return; } @@ -195,8 +195,8 @@ HOOK_METHOD(Level, generate_blue_womb, () -> void) { super(); } -HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 4); +HOOK_METHOD(Level, generate_home_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 3); if (skip) { return; } @@ -204,8 +204,8 @@ HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { super(); } -HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 5); +HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 4); if (skip) { return; } @@ -214,7 +214,7 @@ HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { } HOOK_METHOD(Level, generate_greed_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 6); + bool skip = ProcessGenerateDungeonCallback(this, NULL, 5); if (skip) { return; } diff --git a/repentogon/resources/scripts/enums_ex.lua b/repentogon/resources/scripts/enums_ex.lua index 7a879fa79..9ec3ab52c 100644 --- a/repentogon/resources/scripts/enums_ex.lua +++ b/repentogon/resources/scripts/enums_ex.lua @@ -3082,6 +3082,14 @@ UseActiveItemResultFlag = { REMOVE = 1 << 8, } +GenerateDungeonType = { + NORMAL = 0, + BLUE_WOMB = 1, + BACKWARDS = 2, + HOME = 3, + RED_REDEMPTION = 4, + GREED = 5 +} --deprecated enums From e2f77b486b6d98fc7290ee9e94ffce4e9ba8dd97 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Wed, 5 Nov 2025 18:30:15 +0100 Subject: [PATCH 09/35] Moved custom callback to appropiate file --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 111 +++++++++++++++++++ repentogon/Patches/ASMPatches/ASMLevel.cpp | 104 ----------------- 2 files changed, 111 insertions(+), 104 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index 8b9facead..e476017b0 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -15,6 +15,7 @@ #include "../Patches/MainMenuBlock.h" #include "../Patches/XMLData.h" #include "../Patches/EntityPlus.h" +#include "LuaDungeonGenerator.h" //Callback tracking for optimizations std::bitset<500> CallbackState; // For new REPENTOGON callbacks. I dont think we will add 500 callbacks but lets set it there for now @@ -5646,4 +5647,114 @@ HOOK_STATIC(LuaEngine, PostEntityKill, (Entity* ent) -> void, __stdcall) { .push(lastSource, lua::Metatables::ENTITY_REF) .call(1); } +} + + +//MC_PRE_GENERATE_DUNGEON(1340) +bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { + const int callbackId = 1340; + if (!CallbackState.test(callbackId - 1000)) { + return false; + } + + lua_State* L = g_LuaEngine->_state; + lua::LuaStackProtector protector(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); + + DungeonGenerator* generator = new DungeonGenerator(); + lua::LuaResults results = lua::LuaCaller(L) + .push(callbackId) + .push(dungeonType) + .push(generator, lua::metatables::DungeonGeneratorMT) + .push(rng, lua::Metatables::RNG) + .call(1); + + if (results || !lua_isboolean(L, -1) || !lua_toboolean(L, -1)) + { + return false; + } + + level->reset_room_list(false); + + for (size_t i = 0; i < 507; i++) + { + g_Game->_roomOffset[i] = -1; + } + + g_Game->_nbRooms = 0; + + for (size_t i = 0; i < generator->num_rooms; i++) + { + DungeonGeneratorRoom generator_room = generator->rooms[i]; + + if (generator_room.room != NULL) { + LevelGenerator_Room* level_generator_room = new LevelGenerator_Room(); + level_generator_room->_gridColIdx = generator_room.col; + level_generator_room->_gridLineIdx = generator_room.row; + level_generator_room->_doors = 15; + + g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); + + if (generator_room.is_final_boss) { + g_Game->_lastBossRoomListIdx = i; + } + } + } + + return true; +} + +HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) +{ + bool skip = ProcessGenerateDungeonCallback(this, rng, 0); + if (skip) { + return; + } + + super(rng); +} + +HOOK_METHOD(Level, generate_blue_womb, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 1); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 2); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_home_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 3); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 4); + if (skip) { + return; + } + + super(); +} + +HOOK_METHOD(Level, generate_greed_dungeon, () -> void) { + bool skip = ProcessGenerateDungeonCallback(this, NULL, 5); + if (skip) { + return; + } + + super(); } \ No newline at end of file diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index a9cb5f8ef..b9c9768e0 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -83,67 +83,8 @@ void ASMPatchVoidGeneration() { sASMPatcher.PatchAt(addr, &patch); } -//MC_PRE_GENERATE_DUNGEON(1340) -bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { - const int callbackId = 1340; - if (!CallbackState.test(callbackId - 1000)) { - return false; - } - - lua_State* L = g_LuaEngine->_state; - lua::LuaStackProtector protector(L); - lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - - DungeonGenerator* generator = new DungeonGenerator(); - lua::LuaResults results = lua::LuaCaller(L) - .push(callbackId) - .push(dungeonType) - .push(generator, lua::metatables::DungeonGeneratorMT) - .push(rng, lua::Metatables::RNG) - .call(1); - - if (results || !lua_isboolean(L, -1) || !lua_toboolean(L, -1)) - { - return false; - } - - level->reset_room_list(false); - - for (size_t i = 0; i < 507; i++) - { - g_Game->_roomOffset[i] = -1; - } - - g_Game->_nbRooms = 0; - - for (size_t i = 0; i < generator->num_rooms; i++) - { - DungeonGeneratorRoom generator_room = generator->rooms[i]; - - if (generator_room.room != NULL) { - LevelGenerator_Room* level_generator_room = new LevelGenerator_Room(); - level_generator_room->_gridColIdx = generator_room.col; - level_generator_room->_gridLineIdx = generator_room.row; - level_generator_room->_doors = 15; - - g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); - - if (generator_room.is_final_boss) { - g_Game->_lastBossRoomListIdx = i; - } - } - } - - return true; -} - HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { - bool skip = ProcessGenerateDungeonCallback(this, rng, 0); - if (skip) { - return; - } - if (this->_stage == 12) { if (generateLevels.any()) @@ -177,51 +118,6 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) super(rng); } -HOOK_METHOD(Level, generate_blue_womb, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 1); - if (skip) { - return; - } - - super(); -} - -HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 2); - if (skip) { - return; - } - - super(); -} - -HOOK_METHOD(Level, generate_home_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 3); - if (skip) { - return; - } - - super(); -} - -HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 4); - if (skip) { - return; - } - - super(); -} - -HOOK_METHOD(Level, generate_greed_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 5); - if (skip) { - return; - } - - super(); -} - bool __stdcall SpawnSpecialQuestDoorValidStageTypeCheck() { // Always return true if we forced it via Room:TrySpawnSpecialQuestDoor bool ret = roomASM.ForceSpecialQuestDoor; From 32e508d1e06cea38a23e8b8611ca3f65a1d51193 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Wed, 5 Nov 2025 18:32:59 +0100 Subject: [PATCH 10/35] Fixed return values for lua functions --- repentogon/LuaInterfaces/LuaDungeonGenerator.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 1e7da8f8e..fe115e3c2 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -21,6 +21,8 @@ LUA_FUNCTION(place_room) { generator->num_rooms++; + lua_pushboolean(L, true); + return 1; } @@ -43,7 +45,7 @@ LUA_FUNCTION(set_final_boss_room) { } } - return 1; + return 0; } static void RegisterDungeonGenerator(lua_State* L) { From 1feba7f5da0b35f4e2015fc49f5cbfc3e7bd0658 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Wed, 5 Nov 2025 18:34:01 +0100 Subject: [PATCH 11/35] Renamed lua functions --- repentogon/LuaInterfaces/LuaDungeonGenerator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index fe115e3c2..5054ccd78 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -9,7 +9,7 @@ DungeonGenerator* GetDungeonGenerator(lua_State* L) { return *lua::GetRawUserdata(L, 1, lua::metatables::DungeonGeneratorMT); } -LUA_FUNCTION(place_room) { +LUA_FUNCTION(Lua_PlaceRoom) { DungeonGenerator* generator = GetDungeonGenerator(L); RoomConfig_Room* config = lua::GetLuabridgeUserdata(L, 2, lua::Metatables::CONST_ROOM_CONFIG_ROOM, "RoomConfig"); uint32_t row = (uint32_t)luaL_checkinteger(L, 3); @@ -26,7 +26,7 @@ LUA_FUNCTION(place_room) { return 1; } -LUA_FUNCTION(set_final_boss_room) { +LUA_FUNCTION(Lua_SetFinalBossRoom) { DungeonGenerator* generator = GetDungeonGenerator(L); uint32_t row = (uint32_t)luaL_checkinteger(L, 2); uint32_t col = (uint32_t)luaL_checkinteger(L, 3); @@ -50,8 +50,8 @@ LUA_FUNCTION(set_final_boss_room) { static void RegisterDungeonGenerator(lua_State* L) { luaL_Reg functions[] = { - {"PlaceRoom", place_room}, - {"SetFinalBossRoom", set_final_boss_room}, + {"PlaceRoom", Lua_PlaceRoom}, + {"SetFinalBossRoom", Lua_SetFinalBossRoom}, { NULL, NULL } }; From bfab985c649ff0926e321fad80dcb3f5d30f56da Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Thu, 6 Nov 2025 18:18:30 +0100 Subject: [PATCH 12/35] PlaceRoom returns the room --- libzhl/LuaCore.cpp | 1 + libzhl/LuaCore.h | 1 + repentogon/LuaInterfaces/CustomCallbacks.cpp | 20 +-------- .../LuaInterfaces/LuaDungeonGenerator.cpp | 36 ++++++++-------- .../LuaInterfaces/LuaDungeonGenerator.h | 41 +++++++++++++++++-- 5 files changed, 58 insertions(+), 41 deletions(-) diff --git a/libzhl/LuaCore.cpp b/libzhl/LuaCore.cpp index 9aace6ca4..e6a175e3e 100644 --- a/libzhl/LuaCore.cpp +++ b/libzhl/LuaCore.cpp @@ -839,6 +839,7 @@ namespace lua { const char* MinimapConfigMT = "MinimapConfig"; const char* EntityDescMT = "EntityDesc"; const char* DungeonGeneratorMT = "DungeonGenerator"; + const char* DungeonGeneratorRoomMT = "DungeonGeneratorRoom"; } void TableAssoc(lua_State* L, std::string const& name, int value) { diff --git a/libzhl/LuaCore.h b/libzhl/LuaCore.h index 187208bf6..792cf6f09 100644 --- a/libzhl/LuaCore.h +++ b/libzhl/LuaCore.h @@ -258,6 +258,7 @@ namespace lua { extern LIBZHL_API const char* MinimapConfigMT; extern LIBZHL_API const char* EntityDescMT; extern LIBZHL_API const char* DungeonGeneratorMT; + extern LIBZHL_API const char* DungeonGeneratorRoomMT; } LIBZHL_API void UnloadMetatables(); diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index e476017b0..018f4f977 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5661,7 +5661,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { lua::LuaStackProtector protector(L); lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - DungeonGenerator* generator = new DungeonGenerator(); + DungeonGenerator* generator = &DungeonGenerator(); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) .push(dungeonType) @@ -5683,23 +5683,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { g_Game->_nbRooms = 0; - for (size_t i = 0; i < generator->num_rooms; i++) - { - DungeonGeneratorRoom generator_room = generator->rooms[i]; - - if (generator_room.room != NULL) { - LevelGenerator_Room* level_generator_room = new LevelGenerator_Room(); - level_generator_room->_gridColIdx = generator_room.col; - level_generator_room->_gridLineIdx = generator_room.row; - level_generator_room->_doors = 15; - - g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); - - if (generator_room.is_final_boss) { - g_Game->_lastBossRoomListIdx = i; - } - } - } + generator->Generate(); return true; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 5054ccd78..f5efe0af5 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -16,34 +16,20 @@ LUA_FUNCTION(Lua_PlaceRoom) { uint32_t col = (uint32_t)luaL_checkinteger(L, 4); uint32_t seed = (uint32_t)luaL_checkinteger(L, 5); - DungeonGeneratorRoom* generatorRoom = new DungeonGeneratorRoom(config, row, col, seed); - generator->rooms[generator->num_rooms] = *generatorRoom; + DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, row, col, seed); - generator->num_rooms++; - - lua_pushboolean(L, true); + DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); + *ud = generator_room; + luaL_setmetatable(L, lua::metatables::DungeonGeneratorRoomMT); return 1; } LUA_FUNCTION(Lua_SetFinalBossRoom) { DungeonGenerator* generator = GetDungeonGenerator(L); - uint32_t row = (uint32_t)luaL_checkinteger(L, 2); - uint32_t col = (uint32_t)luaL_checkinteger(L, 3); + DungeonGeneratorRoom* generator_room = *lua::GetRawUserdata(L, 2, lua::metatables::DungeonGeneratorRoomMT); - for (size_t i = 0; i < generator->num_rooms; i++) { - DungeonGeneratorRoom* generator_room = &(generator->rooms[i]); - - if (generator_room->room != NULL) { - if (row == generator_room->row && col == generator_room->col) { - generator_room->is_final_boss = true; - } else { - generator_room->is_final_boss = false; - } - } else { - break; - } - } + generator->SetFinalBossRoom(generator_room); return 0; } @@ -58,7 +44,17 @@ static void RegisterDungeonGenerator(lua_State* L) { lua::RegisterNewClass(L, lua::metatables::DungeonGeneratorMT, lua::metatables::DungeonGeneratorMT, functions); } +static void RegisterDungeonGeneratorRoom(lua_State* L) { + luaL_Reg functions[] = { + { NULL, NULL } + }; + + lua::RegisterNewClass(L, lua::metatables::DungeonGeneratorRoomMT, lua::metatables::DungeonGeneratorRoomMT, functions); +} + + HOOK_METHOD(LuaEngine, RegisterClasses, () -> void) { super(); RegisterDungeonGenerator(_state); + RegisterDungeonGeneratorRoom(_state); } \ No newline at end of file diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index d6c914d3b..11fed9ec1 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -8,7 +8,7 @@ struct DungeonGeneratorRoom { bool is_final_boss = false; DungeonGeneratorRoom() { - this->room = NULL; + this->room = nullptr; this->row = -1; this->col = -1; this->seed = -1; @@ -23,12 +23,47 @@ struct DungeonGeneratorRoom { }; struct DungeonGenerator { - int a; int num_rooms; DungeonGeneratorRoom rooms[169]; DungeonGenerator() { - a = 0; num_rooms = 0; } + + DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col, uint32_t seed) { + this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, row, col, seed); + this->num_rooms++; + DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; + + return generatorRoom; + } + + void SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { + for (size_t i = 0; i < num_rooms; i++) + { + this->rooms[i].is_final_boss = false; + } + + boss_room->is_final_boss = true; + } + + void Generate() { + for (size_t i = 0; i < this->num_rooms; i++) + { + DungeonGeneratorRoom generator_room = this->rooms[i]; + + if (generator_room.room != NULL) { + LevelGenerator_Room* level_generator_room = &LevelGenerator_Room(); + level_generator_room->_gridColIdx = generator_room.col; + level_generator_room->_gridLineIdx = generator_room.row; + level_generator_room->_doors = 15; + + g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); + + if (generator_room.is_final_boss) { + g_Game->_lastBossRoomListIdx = i; + } + } + } + } }; \ No newline at end of file From 845072ce4be1a026c2ae7b98daf7157dcd27e659 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Thu, 6 Nov 2025 18:25:33 +0100 Subject: [PATCH 13/35] Generator returns bool --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 4 ++-- repentogon/LuaInterfaces/LuaDungeonGenerator.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index 018f4f977..ec018858b 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5683,9 +5683,9 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { g_Game->_nbRooms = 0; - generator->Generate(); + bool correctGeneration = generator->Generate(); - return true; + return correctGeneration; } HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 11fed9ec1..c77b0b8f1 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -47,12 +47,12 @@ struct DungeonGenerator { boss_room->is_final_boss = true; } - void Generate() { + bool Generate() { for (size_t i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom generator_room = this->rooms[i]; - if (generator_room.room != NULL) { + if (generator_room.room != nullptr) { LevelGenerator_Room* level_generator_room = &LevelGenerator_Room(); level_generator_room->_gridColIdx = generator_room.col; level_generator_room->_gridLineIdx = generator_room.row; @@ -65,5 +65,7 @@ struct DungeonGenerator { } } } + + return true; } }; \ No newline at end of file From c2cc975f78acf3149bc6e9fb6d1e21150ce6ab43 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 13:38:32 +0100 Subject: [PATCH 14/35] Dungeon generator has own RNG --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 19 +++++++++++++------ .../LuaInterfaces/LuaDungeonGenerator.cpp | 3 +-- .../LuaInterfaces/LuaDungeonGenerator.h | 17 +++++++++-------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index ec018858b..10736dd15 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5661,7 +5661,14 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { lua::LuaStackProtector protector(L); lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - DungeonGenerator* generator = &DungeonGenerator(); + if (rng == nullptr) { + rng = &RNG(); + + unsigned int stage_seed = g_Game->_seedEffects._stageSeeds[g_Game->_stage]; + rng->SetSeed(stage_seed, 35); + } + + DungeonGenerator* generator = &DungeonGenerator(rng); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) .push(dungeonType) @@ -5699,7 +5706,7 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) } HOOK_METHOD(Level, generate_blue_womb, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 1); + bool skip = ProcessGenerateDungeonCallback(this, nullptr, 1); if (skip) { return; } @@ -5708,7 +5715,7 @@ HOOK_METHOD(Level, generate_blue_womb, () -> void) { } HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 2); + bool skip = ProcessGenerateDungeonCallback(this, nullptr, 2); if (skip) { return; } @@ -5717,7 +5724,7 @@ HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { } HOOK_METHOD(Level, generate_home_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 3); + bool skip = ProcessGenerateDungeonCallback(this, nullptr, 3); if (skip) { return; } @@ -5726,7 +5733,7 @@ HOOK_METHOD(Level, generate_home_dungeon, () -> void) { } HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 4); + bool skip = ProcessGenerateDungeonCallback(this, nullptr, 4); if (skip) { return; } @@ -5735,7 +5742,7 @@ HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { } HOOK_METHOD(Level, generate_greed_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, NULL, 5); + bool skip = ProcessGenerateDungeonCallback(this, nullptr, 5); if (skip) { return; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index f5efe0af5..6a8d00314 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -14,9 +14,8 @@ LUA_FUNCTION(Lua_PlaceRoom) { RoomConfig_Room* config = lua::GetLuabridgeUserdata(L, 2, lua::Metatables::CONST_ROOM_CONFIG_ROOM, "RoomConfig"); uint32_t row = (uint32_t)luaL_checkinteger(L, 3); uint32_t col = (uint32_t)luaL_checkinteger(L, 4); - uint32_t seed = (uint32_t)luaL_checkinteger(L, 5); - DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, row, col, seed); + DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, row, col); DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); *ud = generator_room; diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index c77b0b8f1..e584b9523 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -4,34 +4,33 @@ struct DungeonGeneratorRoom { RoomConfig_Room* room; uint32_t row; uint32_t col; - uint32_t seed; bool is_final_boss = false; DungeonGeneratorRoom() { this->room = nullptr; this->row = -1; this->col = -1; - this->seed = -1; } - DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col, uint32_t seed) { + DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col) { this->room = room; this->row = row; this->col = col; - this->seed = seed; } }; struct DungeonGenerator { int num_rooms; DungeonGeneratorRoom rooms[169]; + RNG* rng; - DungeonGenerator() { + DungeonGenerator(RNG* rng) { num_rooms = 0; + this->rng = rng; } - DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col, uint32_t seed) { - this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, row, col, seed); + DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col) { + this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, row, col); this->num_rooms++; DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; @@ -58,7 +57,9 @@ struct DungeonGenerator { level_generator_room->_gridLineIdx = generator_room.row; level_generator_room->_doors = 15; - g_Game->PlaceRoom(level_generator_room, generator_room.room, generator_room.seed, 0); + uint32_t seed = this->rng->Next(); + + g_Game->PlaceRoom(level_generator_room, generator_room.room, seed, 0); if (generator_room.is_final_boss) { g_Game->_lastBossRoomListIdx = i; From 47dbdd903f591d82d455e5983ee90ec661424ecd Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 13:47:32 +0100 Subject: [PATCH 15/35] Refactored floor generation --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 11 +---- .../LuaInterfaces/LuaDungeonGenerator.h | 42 +++++++++++++++++-- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index 10736dd15..3573017be 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5681,16 +5681,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { return false; } - level->reset_room_list(false); - - for (size_t i = 0; i < 507; i++) - { - g_Game->_roomOffset[i] = -1; - } - - g_Game->_nbRooms = 0; - - bool correctGeneration = generator->Generate(); + bool correctGeneration = generator->Generate(level); return correctGeneration; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index e584b9523..567562ae3 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -25,7 +25,7 @@ struct DungeonGenerator { RNG* rng; DungeonGenerator(RNG* rng) { - num_rooms = 0; + this->num_rooms = 0; this->rng = rng; } @@ -38,7 +38,7 @@ struct DungeonGenerator { } void SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { - for (size_t i = 0; i < num_rooms; i++) + for (size_t i = 0; i < this->num_rooms; i++) { this->rooms[i].is_final_boss = false; } @@ -46,7 +46,33 @@ struct DungeonGenerator { boss_room->is_final_boss = true; } - bool Generate() { + bool ValidateFloor() { + bool has_final_room = false; + + for (size_t i = 0; i < this->num_rooms; i++) + { + DungeonGeneratorRoom room = this->rooms[i]; + if (room.is_final_boss) { + has_final_room = true; + break; + } + } + + return has_final_room; + } + + void CleanFloor(Level* level) { + level->reset_room_list(false); + + for (size_t i = 0; i < 507; i++) + { + g_Game->_roomOffset[i] = -1; + } + + g_Game->_nbRooms = 0; + } + + void PlaceRoomsInFloor() { for (size_t i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom generator_room = this->rooms[i]; @@ -66,6 +92,16 @@ struct DungeonGenerator { } } } + } + + bool Generate(Level* level) { + if (!this->ValidateFloor()) { + return false; + } + + CleanFloor(level); + + PlaceRoomsInFloor(); return true; } From 7d5ce08556e7bf74408950fe3e917bb2ed0caa6b Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 16:52:15 +0100 Subject: [PATCH 16/35] Moved implementations to source file --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 102 ++++++++++++++++++ .../LuaInterfaces/LuaDungeonGenerator.h | 94 ++-------------- 2 files changed, 111 insertions(+), 85 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 6a8d00314..f25b7e724 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -5,6 +5,108 @@ #include "Log.h" #include "LuaDungeonGenerator.h" +#pragma region DungeonGeneratorRoom Impl + +DungeonGeneratorRoom::DungeonGeneratorRoom() { + this->room = nullptr; + this->row = -1; + this->col = -1; +} + +DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col) { + this->room = room; + this->row = row; + this->col = col; +} + +#pragma endregion + +#pragma region DungeonGenerator Impl + +DungeonGenerator::DungeonGenerator(RNG* rng) { + this->num_rooms = 0; + this->rng = rng; +} + +DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col) { + this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, row, col); + this->num_rooms++; + DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; + + return generatorRoom; +} + +void DungeonGenerator::SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { + for (size_t i = 0; i < this->num_rooms; i++) + { + this->rooms[i].is_final_boss = false; + } + + boss_room->is_final_boss = true; +} + +bool DungeonGenerator::ValidateFloor() { + bool has_final_room = false; + + for (size_t i = 0; i < this->num_rooms; i++) + { + DungeonGeneratorRoom room = this->rooms[i]; + if (room.is_final_boss) { + has_final_room = true; + break; + } + } + + return has_final_room; +} + +void DungeonGenerator::CleanFloor(Level* level) { + level->reset_room_list(false); + + for (size_t i = 0; i < 507; i++) + { + g_Game->_roomOffset[i] = -1; + } + + g_Game->_nbRooms = 0; +} + +void DungeonGenerator::PlaceRoomsInFloor() { + for (size_t i = 0; i < this->num_rooms; i++) + { + DungeonGeneratorRoom generator_room = this->rooms[i]; + + if (generator_room.room != nullptr) { + LevelGenerator_Room* level_generator_room = &LevelGenerator_Room(); + level_generator_room->_gridColIdx = generator_room.col; + level_generator_room->_gridLineIdx = generator_room.row; + level_generator_room->_doors = 15; + + uint32_t seed = this->rng->Next(); + + g_Game->PlaceRoom(level_generator_room, generator_room.room, seed, 0); + + if (generator_room.is_final_boss) { + g_Game->_lastBossRoomListIdx = i; + } + } + } +} + +bool DungeonGenerator::Generate(Level* level) { + if (!this->ValidateFloor()) { + return false; + } + + CleanFloor(level); + + PlaceRoomsInFloor(); + + return true; +} + +#pragma endregion + DungeonGenerator* GetDungeonGenerator(lua_State* L) { return *lua::GetRawUserdata(L, 1, lua::metatables::DungeonGeneratorMT); } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 567562ae3..76cb5d118 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -6,17 +6,9 @@ struct DungeonGeneratorRoom { uint32_t col; bool is_final_boss = false; - DungeonGeneratorRoom() { - this->room = nullptr; - this->row = -1; - this->col = -1; - } + DungeonGeneratorRoom(); - DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col) { - this->room = room; - this->row = row; - this->col = col; - } + DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col); }; struct DungeonGenerator { @@ -24,85 +16,17 @@ struct DungeonGenerator { DungeonGeneratorRoom rooms[169]; RNG* rng; - DungeonGenerator(RNG* rng) { - this->num_rooms = 0; - this->rng = rng; - } + DungeonGenerator(RNG* rng); - DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col) { - this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, row, col); - this->num_rooms++; - DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; + DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col); - return generatorRoom; - } + void SetFinalBossRoom(DungeonGeneratorRoom* boss_room); - void SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { - for (size_t i = 0; i < this->num_rooms; i++) - { - this->rooms[i].is_final_boss = false; - } + bool ValidateFloor(); - boss_room->is_final_boss = true; - } + void CleanFloor(Level* level); - bool ValidateFloor() { - bool has_final_room = false; + void DungeonGenerator::PlaceRoomsInFloor(); - for (size_t i = 0; i < this->num_rooms; i++) - { - DungeonGeneratorRoom room = this->rooms[i]; - if (room.is_final_boss) { - has_final_room = true; - break; - } - } - - return has_final_room; - } - - void CleanFloor(Level* level) { - level->reset_room_list(false); - - for (size_t i = 0; i < 507; i++) - { - g_Game->_roomOffset[i] = -1; - } - - g_Game->_nbRooms = 0; - } - - void PlaceRoomsInFloor() { - for (size_t i = 0; i < this->num_rooms; i++) - { - DungeonGeneratorRoom generator_room = this->rooms[i]; - - if (generator_room.room != nullptr) { - LevelGenerator_Room* level_generator_room = &LevelGenerator_Room(); - level_generator_room->_gridColIdx = generator_room.col; - level_generator_room->_gridLineIdx = generator_room.row; - level_generator_room->_doors = 15; - - uint32_t seed = this->rng->Next(); - - g_Game->PlaceRoom(level_generator_room, generator_room.room, seed, 0); - - if (generator_room.is_final_boss) { - g_Game->_lastBossRoomListIdx = i; - } - } - } - } - - bool Generate(Level* level) { - if (!this->ValidateFloor()) { - return false; - } - - CleanFloor(level); - - PlaceRoomsInFloor(); - - return true; - } + bool Generate(Level* level); }; \ No newline at end of file From 57a718d52170312f33d238db1fe2fc194aa90b97 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 17:55:25 +0100 Subject: [PATCH 17/35] Added room shape check and swapped col/row --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 142 ++++++++++++++++-- .../LuaInterfaces/LuaDungeonGenerator.h | 4 +- 2 files changed, 133 insertions(+), 13 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index f25b7e724..cf0845cb0 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -4,19 +4,95 @@ #include "Exception.h" #include "Log.h" #include "LuaDungeonGenerator.h" +#include "vector" + +#pragma region RoomCoords + +struct RoomCoords { + uint32_t col; + uint32_t row; + + RoomCoords(uint32_t col, uint32_t row) { + this->col = col; + this->row = row; + } + + bool IsValid() { + return row >= 0 && row <= 13 && col >= 0 && col <= 13; + } +}; + +#pragma endregion + +#pragma region Helpers + +std::vector GetOccupiedCoords(RoomCoords* base_coords, int shape) { + std::vector occupied_coords = {}; + + switch (shape) + { + case ROOMSHAPE_1x1: + case ROOMSHAPE_IH: + case ROOMSHAPE_IV: + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + break; + case ROOMSHAPE_1x2: + case ROOMSHAPE_IIV: + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + break; + case ROOMSHAPE_2x1: + case ROOMSHAPE_IIH: + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + break; + case ROOMSHAPE_2x2: + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + break; + case ROOMSHAPE_LTL: + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + break; + case ROOMSHAPE_LTR: + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + break; + case ROOMSHAPE_LBL: + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + break; + case ROOMSHAPE_LBR: + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + break; + default: + break; + } + + return occupied_coords; +} + +#pragma endregion #pragma region DungeonGeneratorRoom Impl DungeonGeneratorRoom::DungeonGeneratorRoom() { this->room = nullptr; - this->row = -1; this->col = -1; + this->row = -1; } -DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col) { +DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t col, uint32_t row) { this->room = room; - this->row = row; this->col = col; + this->row = row; } #pragma endregion @@ -28,8 +104,43 @@ DungeonGenerator::DungeonGenerator(RNG* rng) { this->rng = rng; } -DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col) { - this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, row, col); +bool DungeonGenerator::CanRoomBePlaced(uint32_t row, uint32_t col, int room_shape, uint32_t doors) { + RoomCoords* base_coords = &RoomCoords(col, row); + if (!base_coords->IsValid()) { + KAGE::_LogMessage(0, "[SEX] Base coordinates aren't valid. %d-%d\n", base_coords->row, base_coords->col); + return false; + } + + std::vector occupied_coords = GetOccupiedCoords(base_coords, room_shape); + for (RoomCoords coords : occupied_coords) { + if (!coords.IsValid()) { + KAGE::_LogMessage(0, "[SEX] Occupied coordinates aren't valid. %d-%d\n", base_coords->row, base_coords->col); + return false; + } + } + + for (size_t i = 0; i < this->num_rooms; i++) { + DungeonGeneratorRoom room = this->rooms[i]; + + RoomCoords* other_base_coords = &RoomCoords(room.col, room.row); + std::vector other_occupied_coords = GetOccupiedCoords(other_base_coords, room.room->Shape); + + for (RoomCoords coords : occupied_coords) { + for (RoomCoords other_coords : other_occupied_coords) { + if (coords.col == other_coords.col && coords.row == other_coords.row) { + KAGE::_LogMessage(0, "[SEX] Occupied coordinates conflict with other. %d-%d\n", base_coords->row, base_coords->col); + + return false; + } + } + } + } + + return true; +} + +DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row) { + this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, col, row); this->num_rooms++; DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; @@ -114,16 +225,23 @@ DungeonGenerator* GetDungeonGenerator(lua_State* L) { LUA_FUNCTION(Lua_PlaceRoom) { DungeonGenerator* generator = GetDungeonGenerator(L); RoomConfig_Room* config = lua::GetLuabridgeUserdata(L, 2, lua::Metatables::CONST_ROOM_CONFIG_ROOM, "RoomConfig"); - uint32_t row = (uint32_t)luaL_checkinteger(L, 3); - uint32_t col = (uint32_t)luaL_checkinteger(L, 4); + uint32_t col = (uint32_t)luaL_checkinteger(L, 3); + uint32_t row = (uint32_t)luaL_checkinteger(L, 4); + uint32_t doors = (uint32_t)luaL_checkinteger(L, 5); - DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, row, col); + doors = doors | config->Doors; - DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); - *ud = generator_room; - luaL_setmetatable(L, lua::metatables::DungeonGeneratorRoomMT); + if (generator->CanRoomBePlaced(row, col, config->Shape, doors)) { + DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row); - return 1; + DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); + *ud = generator_room; + luaL_setmetatable(L, lua::metatables::DungeonGeneratorRoomMT); + + return 1; + } else { + return 0; + } } LUA_FUNCTION(Lua_SetFinalBossRoom) { diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 76cb5d118..94344772d 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -2,8 +2,8 @@ struct DungeonGeneratorRoom { RoomConfig_Room* room; - uint32_t row; uint32_t col; + uint32_t row; bool is_final_boss = false; DungeonGeneratorRoom(); @@ -18,6 +18,8 @@ struct DungeonGenerator { DungeonGenerator(RNG* rng); + bool CanRoomBePlaced(uint32_t row, uint32_t col, int shape, uint32_t doors); + DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col); void SetFinalBossRoom(DungeonGeneratorRoom* boss_room); From 05c839abe30e3d804948a199b02a804100aecef4 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 19:03:10 +0100 Subject: [PATCH 18/35] Added door validation --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 265 +++++++++++++++++- .../LuaInterfaces/LuaDungeonGenerator.h | 5 +- 2 files changed, 260 insertions(+), 10 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index cf0845cb0..f87f33e86 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -20,6 +20,10 @@ struct RoomCoords { bool IsValid() { return row >= 0 && row <= 13 && col >= 0 && col <= 13; } + + bool operator==(RoomCoords const& other) const { + return this->row == other.row && this->col == other.col; + } }; #pragma endregion @@ -79,6 +83,234 @@ std::vector GetOccupiedCoords(RoomCoords* base_coords, int shape) { return occupied_coords; } +std::vector GetForbiddenNeighbors(RoomCoords* base_coords, int shape, uint32_t doors) { + std::vector forbidden_neighbors = {}; + + switch (shape) + { + case ROOMSHAPE_1x1: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + } + break; + case ROOMSHAPE_IH: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + break; + case ROOMSHAPE_IV: + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + } + break; + case ROOMSHAPE_1x2: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + } + break; + case ROOMSHAPE_IIV: + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + break; + case ROOMSHAPE_2x1: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + } + break; + case ROOMSHAPE_IIH: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + break; + case ROOMSHAPE_2x2: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + } + break; + case ROOMSHAPE_LTL: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0 || (doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + } + break; + case ROOMSHAPE_LTR: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0 || (doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + } + break; + case ROOMSHAPE_LBL: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0 || (doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + } + break; + case ROOMSHAPE_LBR: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0 || (doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + } + break; + default: + break; + } + + return forbidden_neighbors; +} + #pragma endregion #pragma region DungeonGeneratorRoom Impl @@ -89,10 +321,11 @@ DungeonGeneratorRoom::DungeonGeneratorRoom() { this->row = -1; } -DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t col, uint32_t row) { +DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t col, uint32_t row, uint32_t doors) { this->room = room; this->col = col; this->row = row; + this->doors = doors; } #pragma endregion @@ -119,17 +352,32 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t row, uint32_t col, int room_shap } } + std::vector forbidden_coords = GetForbiddenNeighbors(base_coords, room_shape, doors); + for (size_t i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom room = this->rooms[i]; RoomCoords* other_base_coords = &RoomCoords(room.col, room.row); std::vector other_occupied_coords = GetOccupiedCoords(other_base_coords, room.room->Shape); + std::vector other_forbidden_coords = GetForbiddenNeighbors(other_base_coords, room.room->Shape, doors); for (RoomCoords coords : occupied_coords) { for (RoomCoords other_coords : other_occupied_coords) { - if (coords.col == other_coords.col && coords.row == other_coords.row) { - KAGE::_LogMessage(0, "[SEX] Occupied coordinates conflict with other. %d-%d\n", base_coords->row, base_coords->col); + if (coords == other_coords) { + return false; + } + + for (RoomCoords forbidden_coord : forbidden_coords) + { + if (forbidden_coord == other_coords) { + return false; + } + } + } + for (RoomCoords other_forbidden_coord : other_forbidden_coords) + { + if (other_forbidden_coord == coords) { return false; } } @@ -139,8 +387,8 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t row, uint32_t col, int room_shap return true; } -DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row) { - this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, col, row); +DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row, uint32_t doors) { + this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, col, row, doors); this->num_rooms++; DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; @@ -191,7 +439,7 @@ void DungeonGenerator::PlaceRoomsInFloor() { LevelGenerator_Room* level_generator_room = &LevelGenerator_Room(); level_generator_room->_gridColIdx = generator_room.col; level_generator_room->_gridLineIdx = generator_room.row; - level_generator_room->_doors = 15; + level_generator_room->_doors = generator_room.doors; uint32_t seed = this->rng->Next(); @@ -229,10 +477,11 @@ LUA_FUNCTION(Lua_PlaceRoom) { uint32_t row = (uint32_t)luaL_checkinteger(L, 4); uint32_t doors = (uint32_t)luaL_checkinteger(L, 5); - doors = doors | config->Doors; + // Can't have more doors than what the config allows. + doors = doors & config->Doors; if (generator->CanRoomBePlaced(row, col, config->Shape, doors)) { - DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row); + DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row, doors); DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); *ud = generator_room; diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 94344772d..0e141bbec 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -4,11 +4,12 @@ struct DungeonGeneratorRoom { RoomConfig_Room* room; uint32_t col; uint32_t row; + uint32_t doors; bool is_final_boss = false; DungeonGeneratorRoom(); - DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col); + DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col, uint32_t doors); }; struct DungeonGenerator { @@ -20,7 +21,7 @@ struct DungeonGenerator { bool CanRoomBePlaced(uint32_t row, uint32_t col, int shape, uint32_t doors); - DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col); + DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col, uint32_t doors); void SetFinalBossRoom(DungeonGeneratorRoom* boss_room); From 9a7e37eadb2c35ec6913657911be57d4ecffedab Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 19:24:59 +0100 Subject: [PATCH 19/35] Added shape field to DungeonGeneratorRoom --- repentogon/LuaInterfaces/LuaDungeonGenerator.cpp | 12 ++++++------ repentogon/LuaInterfaces/LuaDungeonGenerator.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index f87f33e86..28f1206b2 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -326,6 +326,8 @@ DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t col, this->col = col; this->row = row; this->doors = doors; + + this->shape = room->Shape; } #pragma endregion @@ -337,17 +339,15 @@ DungeonGenerator::DungeonGenerator(RNG* rng) { this->rng = rng; } -bool DungeonGenerator::CanRoomBePlaced(uint32_t row, uint32_t col, int room_shape, uint32_t doors) { +bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shape, uint32_t doors) { RoomCoords* base_coords = &RoomCoords(col, row); if (!base_coords->IsValid()) { - KAGE::_LogMessage(0, "[SEX] Base coordinates aren't valid. %d-%d\n", base_coords->row, base_coords->col); return false; } std::vector occupied_coords = GetOccupiedCoords(base_coords, room_shape); for (RoomCoords coords : occupied_coords) { if (!coords.IsValid()) { - KAGE::_LogMessage(0, "[SEX] Occupied coordinates aren't valid. %d-%d\n", base_coords->row, base_coords->col); return false; } } @@ -358,8 +358,8 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t row, uint32_t col, int room_shap DungeonGeneratorRoom room = this->rooms[i]; RoomCoords* other_base_coords = &RoomCoords(room.col, room.row); - std::vector other_occupied_coords = GetOccupiedCoords(other_base_coords, room.room->Shape); - std::vector other_forbidden_coords = GetForbiddenNeighbors(other_base_coords, room.room->Shape, doors); + std::vector other_occupied_coords = GetOccupiedCoords(other_base_coords, room.shape); + std::vector other_forbidden_coords = GetForbiddenNeighbors(other_base_coords, room.shape, doors); for (RoomCoords coords : occupied_coords) { for (RoomCoords other_coords : other_occupied_coords) { @@ -480,7 +480,7 @@ LUA_FUNCTION(Lua_PlaceRoom) { // Can't have more doors than what the config allows. doors = doors & config->Doors; - if (generator->CanRoomBePlaced(row, col, config->Shape, doors)) { + if (generator->CanRoomBePlaced(col, row, config->Shape, doors)) { DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row, doors); DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 0e141bbec..5e7c2adf9 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -5,6 +5,7 @@ struct DungeonGeneratorRoom { uint32_t col; uint32_t row; uint32_t doors; + int shape; bool is_final_boss = false; DungeonGeneratorRoom(); From 40605fd74de54198dda36685c17c6263c37b12a8 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 20:00:09 +0100 Subject: [PATCH 20/35] Added PlaceDefaultStartingRoom --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 68 ++++++++++++++++--- .../LuaInterfaces/LuaDungeonGenerator.h | 8 +-- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 28f1206b2..2a1a1f53e 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -83,7 +83,7 @@ std::vector GetOccupiedCoords(RoomCoords* base_coords, int shape) { return occupied_coords; } -std::vector GetForbiddenNeighbors(RoomCoords* base_coords, int shape, uint32_t doors) { +std::vector GetForbiddenNeighbors(RoomCoords* base_coords, int shape, int doors) { std::vector forbidden_neighbors = {}; switch (shape) @@ -319,9 +319,12 @@ DungeonGeneratorRoom::DungeonGeneratorRoom() { this->room = nullptr; this->col = -1; this->row = -1; + + this->doors = -1; + this->shape = -1; } -DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t col, uint32_t row, uint32_t doors) { +DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t col, uint32_t row, int doors) { this->room = room; this->col = col; this->row = row; @@ -339,7 +342,7 @@ DungeonGenerator::DungeonGenerator(RNG* rng) { this->rng = rng; } -bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shape, uint32_t doors) { +bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shape, int doors) { RoomCoords* base_coords = &RoomCoords(col, row); if (!base_coords->IsValid()) { return false; @@ -354,7 +357,7 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shap std::vector forbidden_coords = GetForbiddenNeighbors(base_coords, room_shape, doors); - for (size_t i = 0; i < this->num_rooms; i++) { + for (int i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom room = this->rooms[i]; RoomCoords* other_base_coords = &RoomCoords(room.col, room.row); @@ -387,7 +390,7 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shap return true; } -DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row, uint32_t doors) { +DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row, int doors) { this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, col, row, doors); this->num_rooms++; DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; @@ -396,7 +399,7 @@ DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, } void DungeonGenerator::SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { - for (size_t i = 0; i < this->num_rooms; i++) + for (int i = 0; i < this->num_rooms; i++) { this->rooms[i].is_final_boss = false; } @@ -407,7 +410,7 @@ void DungeonGenerator::SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { bool DungeonGenerator::ValidateFloor() { bool has_final_room = false; - for (size_t i = 0; i < this->num_rooms; i++) + for (int i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom room = this->rooms[i]; if (room.is_final_boss) { @@ -431,7 +434,7 @@ void DungeonGenerator::CleanFloor(Level* level) { } void DungeonGenerator::PlaceRoomsInFloor() { - for (size_t i = 0; i < this->num_rooms; i++) + for (int i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom generator_room = this->rooms[i]; @@ -475,7 +478,7 @@ LUA_FUNCTION(Lua_PlaceRoom) { RoomConfig_Room* config = lua::GetLuabridgeUserdata(L, 2, lua::Metatables::CONST_ROOM_CONFIG_ROOM, "RoomConfig"); uint32_t col = (uint32_t)luaL_checkinteger(L, 3); uint32_t row = (uint32_t)luaL_checkinteger(L, 4); - uint32_t doors = (uint32_t)luaL_checkinteger(L, 5); + int doors = (int)luaL_optinteger(L, 5, 255); // Can't have more doors than what the config allows. doors = doors & config->Doors; @@ -493,6 +496,52 @@ LUA_FUNCTION(Lua_PlaceRoom) { } } +LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { + DungeonGenerator* generator = GetDungeonGenerator(L); + + int doors = (int)luaL_optinteger(L, 2, 15); + + uint32_t col = 6; + uint32_t row = 6; + + KAGE::_LogMessage(0, "[SEX] Before validation\n"); + if (generator->CanRoomBePlaced(col, row, ROOMSHAPE_1x1, doors)) { + int required_doors = 0; + + KAGE::_LogMessage(0, "[SEX] Before room config\n"); + RoomConfig* room_config = g_Game->GetRoomConfig(); + KAGE::_LogMessage(0, "[SEX] Before random room\n"); + RoomConfig_Room* config = room_config->GetRandomRoom( + generator->rng->Next(), + false, + STB_SPECIAL_ROOMS, + ROOM_DEFAULT, + ROOMSHAPE_1x1, + 2, + 2, + 0, + 10, + (unsigned int*)&required_doors, // If I don't do it like this it shits itself + 0, + -1 + ); + + KAGE::_LogMessage(0, "[SEX] Before place room\n"); + + DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row, doors); + + DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); + *ud = generator_room; + luaL_setmetatable(L, lua::metatables::DungeonGeneratorRoomMT); + + return 1; + } + else { + return 0; + } +} + + LUA_FUNCTION(Lua_SetFinalBossRoom) { DungeonGenerator* generator = GetDungeonGenerator(L); DungeonGeneratorRoom* generator_room = *lua::GetRawUserdata(L, 2, lua::metatables::DungeonGeneratorRoomMT); @@ -506,6 +555,7 @@ static void RegisterDungeonGenerator(lua_State* L) { luaL_Reg functions[] = { {"PlaceRoom", Lua_PlaceRoom}, {"SetFinalBossRoom", Lua_SetFinalBossRoom}, + {"PlaceDefaultStartingRoom", Lua_PlaceDefaultStartingRoom}, { NULL, NULL } }; diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 5e7c2adf9..014819f8b 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -4,13 +4,13 @@ struct DungeonGeneratorRoom { RoomConfig_Room* room; uint32_t col; uint32_t row; - uint32_t doors; + int doors; int shape; bool is_final_boss = false; DungeonGeneratorRoom(); - DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col, uint32_t doors); + DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col, int doors); }; struct DungeonGenerator { @@ -20,9 +20,9 @@ struct DungeonGenerator { DungeonGenerator(RNG* rng); - bool CanRoomBePlaced(uint32_t row, uint32_t col, int shape, uint32_t doors); + bool CanRoomBePlaced(uint32_t row, uint32_t col, int shape, int doors); - DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col, uint32_t doors); + DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col, int doors); void SetFinalBossRoom(DungeonGeneratorRoom* boss_room); From 797a52dd3d23d7345218836b437a5f2fbd8e0ed4 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 21:15:33 +0100 Subject: [PATCH 21/35] Fixed constructors --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 6 ++--- .../LuaInterfaces/LuaDungeonGenerator.cpp | 24 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index 3573017be..b46d856c4 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5668,11 +5668,11 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { rng->SetSeed(stage_seed, 35); } - DungeonGenerator* generator = &DungeonGenerator(rng); + DungeonGenerator generator(rng); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) .push(dungeonType) - .push(generator, lua::metatables::DungeonGeneratorMT) + .push(&generator, lua::metatables::DungeonGeneratorMT) .push(rng, lua::Metatables::RNG) .call(1); @@ -5681,7 +5681,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { return false; } - bool correctGeneration = generator->Generate(level); + bool correctGeneration = generator.Generate(level); return correctGeneration; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 2a1a1f53e..562f5add9 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -343,26 +343,26 @@ DungeonGenerator::DungeonGenerator(RNG* rng) { } bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shape, int doors) { - RoomCoords* base_coords = &RoomCoords(col, row); - if (!base_coords->IsValid()) { + RoomCoords base_coords(col, row); + if (!base_coords.IsValid()) { return false; } - std::vector occupied_coords = GetOccupiedCoords(base_coords, room_shape); + std::vector occupied_coords = GetOccupiedCoords(&base_coords, room_shape); for (RoomCoords coords : occupied_coords) { if (!coords.IsValid()) { return false; } } - std::vector forbidden_coords = GetForbiddenNeighbors(base_coords, room_shape, doors); + std::vector forbidden_coords = GetForbiddenNeighbors(&base_coords, room_shape, doors); for (int i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom room = this->rooms[i]; - RoomCoords* other_base_coords = &RoomCoords(room.col, room.row); - std::vector other_occupied_coords = GetOccupiedCoords(other_base_coords, room.shape); - std::vector other_forbidden_coords = GetForbiddenNeighbors(other_base_coords, room.shape, doors); + RoomCoords other_base_coords(room.col, room.row); + std::vector other_occupied_coords = GetOccupiedCoords(&other_base_coords, room.shape); + std::vector other_forbidden_coords = GetForbiddenNeighbors(&other_base_coords, room.shape, doors); for (RoomCoords coords : occupied_coords) { for (RoomCoords other_coords : other_occupied_coords) { @@ -439,14 +439,14 @@ void DungeonGenerator::PlaceRoomsInFloor() { DungeonGeneratorRoom generator_room = this->rooms[i]; if (generator_room.room != nullptr) { - LevelGenerator_Room* level_generator_room = &LevelGenerator_Room(); - level_generator_room->_gridColIdx = generator_room.col; - level_generator_room->_gridLineIdx = generator_room.row; - level_generator_room->_doors = generator_room.doors; + LevelGenerator_Room level_generator_room; + level_generator_room._gridColIdx = generator_room.col; + level_generator_room._gridLineIdx = generator_room.row; + level_generator_room._doors = generator_room.doors; uint32_t seed = this->rng->Next(); - g_Game->PlaceRoom(level_generator_room, generator_room.room, seed, 0); + g_Game->PlaceRoom(&level_generator_room, generator_room.room, seed, 0); if (generator_room.is_final_boss) { g_Game->_lastBossRoomListIdx = i; From 8ad78976646949bb5f05d3ecc11a04f6458135cb Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 21:16:05 +0100 Subject: [PATCH 22/35] Added dungeon type param to callback --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index b46d856c4..b48964f8b 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5674,6 +5674,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { .push(dungeonType) .push(&generator, lua::metatables::DungeonGeneratorMT) .push(rng, lua::Metatables::RNG) + .push(dungeonType) .call(1); if (results || !lua_isboolean(L, -1) || !lua_toboolean(L, -1)) From 2e6f9f44b3366cdfdc9a4889f3ecde7b49ae9ac5 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Fri, 7 Nov 2025 22:05:16 +0100 Subject: [PATCH 23/35] Changed some pointers to references --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 25 +-- .../LuaInterfaces/LuaDungeonGenerator.cpp | 198 +++++++++--------- 2 files changed, 108 insertions(+), 115 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index b48964f8b..1080b8f03 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5651,7 +5651,7 @@ HOOK_STATIC(LuaEngine, PostEntityKill, (Entity* ent) -> void, __stdcall) { //MC_PRE_GENERATE_DUNGEON(1340) -bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { +bool ProcessGenerateDungeonCallback(Level* level, RNG& rng, int dungeonType) { const int callbackId = 1340; if (!CallbackState.test(callbackId - 1000)) { return false; @@ -5661,19 +5661,12 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { lua::LuaStackProtector protector(L); lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - if (rng == nullptr) { - rng = &RNG(); - - unsigned int stage_seed = g_Game->_seedEffects._stageSeeds[g_Game->_stage]; - rng->SetSeed(stage_seed, 35); - } - - DungeonGenerator generator(rng); + DungeonGenerator generator(&rng); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) .push(dungeonType) .push(&generator, lua::metatables::DungeonGeneratorMT) - .push(rng, lua::Metatables::RNG) + .push(&rng, lua::Metatables::RNG) .push(dungeonType) .call(1); @@ -5689,7 +5682,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG* rng, int dungeonType) { HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { - bool skip = ProcessGenerateDungeonCallback(this, rng, 0); + bool skip = ProcessGenerateDungeonCallback(this, *rng, 0); if (skip) { return; } @@ -5698,7 +5691,7 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) } HOOK_METHOD(Level, generate_blue_womb, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, nullptr, 1); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 1); if (skip) { return; } @@ -5707,7 +5700,7 @@ HOOK_METHOD(Level, generate_blue_womb, () -> void) { } HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, nullptr, 2); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 2); if (skip) { return; } @@ -5716,7 +5709,7 @@ HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { } HOOK_METHOD(Level, generate_home_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, nullptr, 3); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 3); if (skip) { return; } @@ -5725,7 +5718,7 @@ HOOK_METHOD(Level, generate_home_dungeon, () -> void) { } HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, nullptr, 4); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 4); if (skip) { return; } @@ -5734,7 +5727,7 @@ HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { } HOOK_METHOD(Level, generate_greed_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, nullptr, 5); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 5); if (skip) { return; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 562f5add9..74ca4e9c4 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -30,7 +30,7 @@ struct RoomCoords { #pragma region Helpers -std::vector GetOccupiedCoords(RoomCoords* base_coords, int shape) { +std::vector GetOccupiedCoords(RoomCoords& base_coords, int shape) { std::vector occupied_coords = {}; switch (shape) @@ -38,43 +38,43 @@ std::vector GetOccupiedCoords(RoomCoords* base_coords, int shape) { case ROOMSHAPE_1x1: case ROOMSHAPE_IH: case ROOMSHAPE_IV: - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); break; case ROOMSHAPE_1x2: case ROOMSHAPE_IIV: - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); break; case ROOMSHAPE_2x1: case ROOMSHAPE_IIH: - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); break; case ROOMSHAPE_2x2: - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); break; case ROOMSHAPE_LTL: - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); break; case ROOMSHAPE_LTR: - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); break; case ROOMSHAPE_LBL: - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); break; case ROOMSHAPE_LBR: - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); - occupied_coords.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); break; default: break; @@ -83,225 +83,225 @@ std::vector GetOccupiedCoords(RoomCoords* base_coords, int shape) { return occupied_coords; } -std::vector GetForbiddenNeighbors(RoomCoords* base_coords, int shape, int doors) { +std::vector GetForbiddenNeighbors(RoomCoords& base_coords, int shape, int doors) { std::vector forbidden_neighbors = {}; switch (shape) { case ROOMSHAPE_1x1: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); } break; case ROOMSHAPE_IH: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); } - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); break; case ROOMSHAPE_IV: - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); } break; case ROOMSHAPE_1x2: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); } break; case ROOMSHAPE_IIV: - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); } - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); break; case ROOMSHAPE_2x1: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); } break; case ROOMSHAPE_IIH: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); } - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); break; case ROOMSHAPE_2x2: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); } break; case ROOMSHAPE_LTL: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0 || (doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); } break; case ROOMSHAPE_LTR: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0 || (doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); } break; case ROOMSHAPE_LBL: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0 || (doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); } break; case ROOMSHAPE_LBR: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 2, base_coords->row)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col, base_coords->row + 2)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col - 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0 || (doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords->col + 1, base_coords->row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); } break; default: @@ -348,21 +348,21 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shap return false; } - std::vector occupied_coords = GetOccupiedCoords(&base_coords, room_shape); + std::vector occupied_coords = GetOccupiedCoords(base_coords, room_shape); for (RoomCoords coords : occupied_coords) { if (!coords.IsValid()) { return false; } } - std::vector forbidden_coords = GetForbiddenNeighbors(&base_coords, room_shape, doors); + std::vector forbidden_coords = GetForbiddenNeighbors(base_coords, room_shape, doors); for (int i = 0; i < this->num_rooms; i++) { DungeonGeneratorRoom room = this->rooms[i]; RoomCoords other_base_coords(room.col, room.row); - std::vector other_occupied_coords = GetOccupiedCoords(&other_base_coords, room.shape); - std::vector other_forbidden_coords = GetForbiddenNeighbors(&other_base_coords, room.shape, doors); + std::vector other_occupied_coords = GetOccupiedCoords(other_base_coords, room.shape); + std::vector other_forbidden_coords = GetForbiddenNeighbors(other_base_coords, room.shape, doors); for (RoomCoords coords : occupied_coords) { for (RoomCoords other_coords : other_occupied_coords) { From e1b7d988d11dff475b9dffdfed444552cadfbd24 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sat, 8 Nov 2025 11:05:28 +0100 Subject: [PATCH 24/35] Changed resetLilPortalRoom param --- libzhl/functions/Level.zhl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libzhl/functions/Level.zhl b/libzhl/functions/Level.zhl index f86d0be4a..407f79aea 100644 --- a/libzhl/functions/Level.zhl +++ b/libzhl/functions/Level.zhl @@ -2,13 +2,13 @@ __thiscall void Level::SetStage(int stageid,int alt); "538bdc83ec0883e4f883c404558b6b??896c24??8bec6aff68????????64a1????????505383ec68a1????????33c58945??5657508d45??64a3????????8bf9897d??8b0d": -__thiscall void Level::Init(bool unkinitStartRoom); +__thiscall void Level::Init(bool resetLilPortalRoom); "518b89????????e8": __thiscall void Level::Update(); "558bec6aff68????????64a1????????5081ecc0000000a1????????33c58945??535657508d45??64a3????????8bc1": -__thiscall void Level::reset_room_list(bool unkinitStartRoom); +__thiscall void Level::reset_room_list(bool resetLilPortalRoom); "558bec6aff68????????64a1????????5083ec2c535657a1????????33c5508d45??64a3????????8bd98b45": __thiscall void Level::ChangeRoom(int targetRoomIDX, int dimension); From bd2415ee4a25fdc56761c3e20b4a0e306389a9f2 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sat, 8 Nov 2025 11:08:09 +0100 Subject: [PATCH 25/35] Removed unnecesary include --- repentogon/Patches/ASMPatches/ASMLevel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/repentogon/Patches/ASMPatches/ASMLevel.cpp b/repentogon/Patches/ASMPatches/ASMLevel.cpp index b9c9768e0..34d51aeb5 100644 --- a/repentogon/Patches/ASMPatches/ASMLevel.cpp +++ b/repentogon/Patches/ASMPatches/ASMLevel.cpp @@ -5,7 +5,6 @@ #include "ASMLevel.h" #include "../../LuaInterfaces/Level.h" #include "../../LuaInterfaces/Room/Room.h" -#include "../../LuaInterfaces/LuaDungeonGenerator.h" std::bitset<36> generateLevels; From 52c50b5ff296643378cf3bc85d7fc6ac15b784db Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sat, 8 Nov 2025 11:27:20 +0100 Subject: [PATCH 26/35] Use bitset to check room placement --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 57 ++++++++++--------- .../LuaInterfaces/LuaDungeonGenerator.h | 4 ++ 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 74ca4e9c4..110d85afb 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -21,6 +21,10 @@ struct RoomCoords { return row >= 0 && row <= 13 && col >= 0 && col <= 13; } + int ToGridIndex() { + return col + row * 13; + } + bool operator==(RoomCoords const& other) const { return this->row == other.row && this->col == other.col; } @@ -353,48 +357,47 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shap if (!coords.IsValid()) { return false; } - } - std::vector forbidden_coords = GetForbiddenNeighbors(base_coords, room_shape, doors); + int gridIndex = coords.ToGridIndex(); - for (int i = 0; i < this->num_rooms; i++) { - DungeonGeneratorRoom room = this->rooms[i]; + if (this->occupied_grid_indexes[gridIndex] || this->forbidden_grid_indexes[gridIndex]) { + return false; + } + } - RoomCoords other_base_coords(room.col, room.row); - std::vector other_occupied_coords = GetOccupiedCoords(other_base_coords, room.shape); - std::vector other_forbidden_coords = GetForbiddenNeighbors(other_base_coords, room.shape, doors); - - for (RoomCoords coords : occupied_coords) { - for (RoomCoords other_coords : other_occupied_coords) { - if (coords == other_coords) { - return false; - } - - for (RoomCoords forbidden_coord : forbidden_coords) - { - if (forbidden_coord == other_coords) { - return false; - } - } - } + std::vector forbidden_coords = GetForbiddenNeighbors(base_coords, room_shape, doors); + for (RoomCoords coords : forbidden_coords) { + int gridIndex = coords.ToGridIndex(); - for (RoomCoords other_forbidden_coord : other_forbidden_coords) - { - if (other_forbidden_coord == coords) { - return false; - } - } + if (this->occupied_grid_indexes[gridIndex]) { + return false; } } return true; } +void DungeonGenerator::FillOccupiedAndForbiddenIndexes(uint32_t row, uint32_t col, int shape, int doors) { + RoomCoords coords(col, row); + + std::vector occupied_coords = GetOccupiedCoords(coords, shape); + for (RoomCoords coords : occupied_coords) { + this->occupied_grid_indexes.set(coords.ToGridIndex()); + } + + std::vector forbidden_coords = GetForbiddenNeighbors(coords, shape, doors); + for (RoomCoords coords : occupied_coords) { + this->forbidden_grid_indexes.set(coords.ToGridIndex()); + } +} + DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row, int doors) { this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, col, row, doors); this->num_rooms++; DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; + FillOccupiedAndForbiddenIndexes(row, col, room_config->Shape, doors); + return generatorRoom; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 014819f8b..07018a59b 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -17,11 +17,15 @@ struct DungeonGenerator { int num_rooms; DungeonGeneratorRoom rooms[169]; RNG* rng; + std::bitset<169> occupied_grid_indexes; + std::bitset<169> forbidden_grid_indexes; DungeonGenerator(RNG* rng); bool CanRoomBePlaced(uint32_t row, uint32_t col, int shape, int doors); + void FillOccupiedAndForbiddenIndexes(uint32_t row, uint32_t col, int shape, int doors); + DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col, int doors); void SetFinalBossRoom(DungeonGeneratorRoom* boss_room); From c308a3ee86462f17a95d286ce02d02814d300372 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sat, 8 Nov 2025 11:43:47 +0100 Subject: [PATCH 27/35] Created utils file and generation type enum --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 14 +- .../LuaInterfaces/LuaDungeonGenerator.cpp | 312 +----------------- .../LuaInterfaces/LuaDungeonGenerator.h | 9 + repentogon/Utils/LevelGenUtils.cpp | 309 +++++++++++++++++ repentogon/Utils/LevelGenUtils.h | 20 ++ 5 files changed, 346 insertions(+), 318 deletions(-) create mode 100644 repentogon/Utils/LevelGenUtils.cpp create mode 100644 repentogon/Utils/LevelGenUtils.h diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index 1080b8f03..c6423a9e2 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5651,7 +5651,7 @@ HOOK_STATIC(LuaEngine, PostEntityKill, (Entity* ent) -> void, __stdcall) { //MC_PRE_GENERATE_DUNGEON(1340) -bool ProcessGenerateDungeonCallback(Level* level, RNG& rng, int dungeonType) { +bool ProcessGenerateDungeonCallback(Level* level, RNG& rng, DungeonGenerationType dungeonType) { const int callbackId = 1340; if (!CallbackState.test(callbackId - 1000)) { return false; @@ -5682,7 +5682,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG& rng, int dungeonType) { HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) { - bool skip = ProcessGenerateDungeonCallback(this, *rng, 0); + bool skip = ProcessGenerateDungeonCallback(this, *rng, DEFAULT); if (skip) { return; } @@ -5691,7 +5691,7 @@ HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void) } HOOK_METHOD(Level, generate_blue_womb, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 1); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, BLUE_WOMB); if (skip) { return; } @@ -5700,7 +5700,7 @@ HOOK_METHOD(Level, generate_blue_womb, () -> void) { } HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 2); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, BACKWARDS); if (skip) { return; } @@ -5709,7 +5709,7 @@ HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) { } HOOK_METHOD(Level, generate_home_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 3); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, HOME); if (skip) { return; } @@ -5718,7 +5718,7 @@ HOOK_METHOD(Level, generate_home_dungeon, () -> void) { } HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 4); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, RED_REDEMPTION); if (skip) { return; } @@ -5727,7 +5727,7 @@ HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) { } HOOK_METHOD(Level, generate_greed_dungeon, () -> void) { - bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, 5); + bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, GREED); if (skip) { return; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 110d85afb..416fde6cd 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -5,317 +5,7 @@ #include "Log.h" #include "LuaDungeonGenerator.h" #include "vector" - -#pragma region RoomCoords - -struct RoomCoords { - uint32_t col; - uint32_t row; - - RoomCoords(uint32_t col, uint32_t row) { - this->col = col; - this->row = row; - } - - bool IsValid() { - return row >= 0 && row <= 13 && col >= 0 && col <= 13; - } - - int ToGridIndex() { - return col + row * 13; - } - - bool operator==(RoomCoords const& other) const { - return this->row == other.row && this->col == other.col; - } -}; - -#pragma endregion - -#pragma region Helpers - -std::vector GetOccupiedCoords(RoomCoords& base_coords, int shape) { - std::vector occupied_coords = {}; - - switch (shape) - { - case ROOMSHAPE_1x1: - case ROOMSHAPE_IH: - case ROOMSHAPE_IV: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - break; - case ROOMSHAPE_1x2: - case ROOMSHAPE_IIV: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - break; - case ROOMSHAPE_2x1: - case ROOMSHAPE_IIH: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - break; - case ROOMSHAPE_2x2: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - break; - case ROOMSHAPE_LTL: - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - break; - case ROOMSHAPE_LTR: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - break; - case ROOMSHAPE_LBL: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - break; - case ROOMSHAPE_LBR: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - break; - default: - break; - } - - return occupied_coords; -} - -std::vector GetForbiddenNeighbors(RoomCoords& base_coords, int shape, int doors) { - std::vector forbidden_neighbors = {}; - - switch (shape) - { - case ROOMSHAPE_1x1: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - } - break; - case ROOMSHAPE_IH: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - break; - case ROOMSHAPE_IV: - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - } - break; - case ROOMSHAPE_1x2: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); - } - if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - } - break; - case ROOMSHAPE_IIV: - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - } - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - break; - case ROOMSHAPE_2x1: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - } - break; - case ROOMSHAPE_IIH: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); - } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - break; - case ROOMSHAPE_2x2: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); - } - if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); - } - break; - case ROOMSHAPE_LTL: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0 || (doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); - } - if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); - } - break; - case ROOMSHAPE_LTR: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0 || (doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); - } - if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); - } - break; - case ROOMSHAPE_LBL: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0 || (doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); - } - break; - case ROOMSHAPE_LBR: - if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); - } - if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); - } - if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); - } - if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); - } - if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0 || (doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); - } - break; - default: - break; - } - - return forbidden_neighbors; -} - -#pragma endregion +#include "../Utils/LevelGenUtils.h" #pragma region DungeonGeneratorRoom Impl diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 07018a59b..554db7d18 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -1,5 +1,14 @@ #pragma once +enum DungeonGenerationType { + DEFAULT, + BLUE_WOMB, + BACKWARDS, + HOME, + RED_REDEMPTION, + GREED, +}; + struct DungeonGeneratorRoom { RoomConfig_Room* room; uint32_t col; diff --git a/repentogon/Utils/LevelGenUtils.cpp b/repentogon/Utils/LevelGenUtils.cpp new file mode 100644 index 000000000..6a729c71b --- /dev/null +++ b/repentogon/Utils/LevelGenUtils.cpp @@ -0,0 +1,309 @@ +#include "LevelGenUtils.h" +#include +#include + +#pragma region RoomCoords struct impl + +RoomCoords::RoomCoords(uint32_t col, uint32_t row) { + this->col = col; + this->row = row; +} + +bool RoomCoords::IsValid() const { + return row >= 0 && row <= 13 && col >= 0 && col <= 13; +} + +int RoomCoords::ToGridIndex() const { + return col + row * 13; +} + +bool RoomCoords::operator==(RoomCoords const& other) const { + return this->row == other.row && this->col == other.col; +} + +#pragma endregion + +#pragma region Helpers + +std::vector GetOccupiedCoords(RoomCoords& base_coords, int shape) { + std::vector occupied_coords = {}; + + switch (shape) + { + case ROOMSHAPE_1x1: + case ROOMSHAPE_IH: + case ROOMSHAPE_IV: + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + break; + case ROOMSHAPE_1x2: + case ROOMSHAPE_IIV: + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + break; + case ROOMSHAPE_2x1: + case ROOMSHAPE_IIH: + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + break; + case ROOMSHAPE_2x2: + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + break; + case ROOMSHAPE_LTL: + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + break; + case ROOMSHAPE_LTR: + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + break; + case ROOMSHAPE_LBL: + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + break; + case ROOMSHAPE_LBR: + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + break; + default: + break; + } + + return occupied_coords; +} + +std::vector GetForbiddenNeighbors(RoomCoords& base_coords, int shape, int doors) { + std::vector forbidden_neighbors = {}; + + switch (shape) + { + case ROOMSHAPE_1x1: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + } + break; + case ROOMSHAPE_IH: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + break; + case ROOMSHAPE_IV: + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + } + break; + case ROOMSHAPE_1x2: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + } + break; + case ROOMSHAPE_IIV: + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + break; + case ROOMSHAPE_2x1: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + } + break; + case ROOMSHAPE_IIH: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + } + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + break; + case ROOMSHAPE_2x2: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + } + break; + case ROOMSHAPE_LTL: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0 || (doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + } + break; + case ROOMSHAPE_LTR: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0 || (doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + } + break; + case ROOMSHAPE_LBL: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0 || (doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + } + break; + case ROOMSHAPE_LBR: + if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + } + if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + } + if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + } + if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + } + if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0 || (doors & (1 << DOOR_SLOT_DOWN1)) == 0) { + forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + } + break; + default: + break; + } + + return forbidden_neighbors; +} + +#pragma endregion \ No newline at end of file diff --git a/repentogon/Utils/LevelGenUtils.h b/repentogon/Utils/LevelGenUtils.h new file mode 100644 index 000000000..2e4999966 --- /dev/null +++ b/repentogon/Utils/LevelGenUtils.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include + +struct RoomCoords { + uint32_t col; + uint32_t row; + + RoomCoords(uint32_t col, uint32_t row); + + bool IsValid() const; + + int ToGridIndex() const; + + bool operator==(RoomCoords const& other) const; +}; + +std::vector GetOccupiedCoords(RoomCoords& base_coords, int shape); + +std::vector GetForbiddenNeighbors(RoomCoords& base_coords, int shape, int doors); \ No newline at end of file From 0bbb1558196f5d357a39db0b0227475f0752b1c3 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sat, 8 Nov 2025 11:47:32 +0100 Subject: [PATCH 28/35] Enum is passed as number to callback --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index c6423a9e2..b582460b7 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5664,10 +5664,10 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG& rng, DungeonGenerationTyp DungeonGenerator generator(&rng); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) - .push(dungeonType) + .push((int)dungeonType) .push(&generator, lua::metatables::DungeonGeneratorMT) .push(&rng, lua::Metatables::RNG) - .push(dungeonType) + .push((int)dungeonType) .call(1); if (results || !lua_isboolean(L, -1) || !lua_toboolean(L, -1)) From d89ff98d09423dbdf6d13c103859ffb151d38294 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sat, 8 Nov 2025 11:56:58 +0100 Subject: [PATCH 29/35] DungeonGenerator now holds index for final boss --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 36 +++++++------------ .../LuaInterfaces/LuaDungeonGenerator.h | 7 ++-- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 416fde6cd..20f1a8805 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -10,6 +10,8 @@ #pragma region DungeonGeneratorRoom Impl DungeonGeneratorRoom::DungeonGeneratorRoom() { + this->list_index = -1; + this->room = nullptr; this->col = -1; this->row = -1; @@ -18,7 +20,9 @@ DungeonGeneratorRoom::DungeonGeneratorRoom() { this->shape = -1; } -DungeonGeneratorRoom::DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t col, uint32_t row, int doors) { +DungeonGeneratorRoom::DungeonGeneratorRoom(int list_index, RoomConfig_Room* room, uint32_t col, uint32_t row, int doors) { + this->list_index = list_index; + this->room = room; this->col = col; this->row = row; @@ -82,9 +86,11 @@ void DungeonGenerator::FillOccupiedAndForbiddenIndexes(uint32_t row, uint32_t co } DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row, int doors) { - this->rooms[this->num_rooms] = DungeonGeneratorRoom(room_config, col, row, doors); + int new_room_list_index = this->num_rooms; + + this->rooms[new_room_list_index] = DungeonGeneratorRoom(new_room_list_index, room_config, col, row, doors); this->num_rooms++; - DungeonGeneratorRoom* generatorRoom = &this->rooms[this->num_rooms - 1]; + DungeonGeneratorRoom* generatorRoom = &this->rooms[new_room_list_index]; FillOccupiedAndForbiddenIndexes(row, col, room_config->Shape, doors); @@ -92,25 +98,11 @@ DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, } void DungeonGenerator::SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { - for (int i = 0; i < this->num_rooms; i++) - { - this->rooms[i].is_final_boss = false; - } - - boss_room->is_final_boss = true; + this->final_boss_index = boss_room->list_index; } bool DungeonGenerator::ValidateFloor() { - bool has_final_room = false; - - for (int i = 0; i < this->num_rooms; i++) - { - DungeonGeneratorRoom room = this->rooms[i]; - if (room.is_final_boss) { - has_final_room = true; - break; - } - } + bool has_final_room = this->final_boss_index >= 0; return has_final_room; } @@ -140,12 +132,10 @@ void DungeonGenerator::PlaceRoomsInFloor() { uint32_t seed = this->rng->Next(); g_Game->PlaceRoom(&level_generator_room, generator_room.room, seed, 0); - - if (generator_room.is_final_boss) { - g_Game->_lastBossRoomListIdx = i; - } } } + + g_Game->_lastBossRoomListIdx = this->final_boss_index; } bool DungeonGenerator::Generate(Level* level) { diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 554db7d18..02a11a1aa 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -15,11 +15,12 @@ struct DungeonGeneratorRoom { uint32_t row; int doors; int shape; - bool is_final_boss = false; + + int list_index; DungeonGeneratorRoom(); - DungeonGeneratorRoom(RoomConfig_Room* room, uint32_t row, uint32_t col, int doors); + DungeonGeneratorRoom(int list_index, RoomConfig_Room* room, uint32_t row, uint32_t col, int doors); }; struct DungeonGenerator { @@ -29,6 +30,8 @@ struct DungeonGenerator { std::bitset<169> occupied_grid_indexes; std::bitset<169> forbidden_grid_indexes; + int final_boss_index = -1; + DungeonGenerator(RNG* rng); bool CanRoomBePlaced(uint32_t row, uint32_t col, int shape, int doors); From fc5098b2eefb0db6c8b8044de45fcfdc5f66a4b7 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sat, 8 Nov 2025 13:18:21 +0100 Subject: [PATCH 30/35] Removed some debug logs --- repentogon/LuaInterfaces/LuaDungeonGenerator.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 20f1a8805..00e9dd085 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -80,7 +80,7 @@ void DungeonGenerator::FillOccupiedAndForbiddenIndexes(uint32_t row, uint32_t co } std::vector forbidden_coords = GetForbiddenNeighbors(coords, shape, doors); - for (RoomCoords coords : occupied_coords) { + for (RoomCoords coords : forbidden_coords) { this->forbidden_grid_indexes.set(coords.ToGridIndex()); } } @@ -187,13 +187,12 @@ LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { uint32_t col = 6; uint32_t row = 6; - KAGE::_LogMessage(0, "[SEX] Before validation\n"); + KAGE::_LogMessage(0, "[SEX] dungeon %d\n", doors); + if (generator->CanRoomBePlaced(col, row, ROOMSHAPE_1x1, doors)) { int required_doors = 0; - KAGE::_LogMessage(0, "[SEX] Before room config\n"); RoomConfig* room_config = g_Game->GetRoomConfig(); - KAGE::_LogMessage(0, "[SEX] Before random room\n"); RoomConfig_Room* config = room_config->GetRandomRoom( generator->rng->Next(), false, @@ -209,8 +208,6 @@ LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { -1 ); - KAGE::_LogMessage(0, "[SEX] Before place room\n"); - DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row, doors); DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); From 6edd184efebd4aa029e506d63e15c97603d53ea6 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Sun, 9 Nov 2025 16:03:39 +0100 Subject: [PATCH 31/35] Refactored DungeonGenerator to use LevelGenerator --- .../LuaInterfaces/LuaDungeonGenerator.cpp | 118 ++++++---- .../LuaInterfaces/LuaDungeonGenerator.h | 9 +- repentogon/Utils/LevelGenUtils.cpp | 219 ++++++++---------- repentogon/Utils/LevelGenUtils.h | 18 +- 4 files changed, 180 insertions(+), 184 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 00e9dd085..f31a6b20f 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -31,6 +31,14 @@ DungeonGeneratorRoom::DungeonGeneratorRoom(int list_index, RoomConfig_Room* room this->shape = room->Shape; } +RoomConfig_Room* DungeonGeneratorRoom::GetRoomConfig(uint32_t seed, int required_doors) { + if (this->room != nullptr) { + return this->room; + } + + return nullptr; +} + #pragma endregion #pragma region DungeonGenerator Impl @@ -38,32 +46,35 @@ DungeonGeneratorRoom::DungeonGeneratorRoom(int list_index, RoomConfig_Room* room DungeonGenerator::DungeonGenerator(RNG* rng) { this->num_rooms = 0; this->rng = rng; + + this->level_generator._rng = *rng; + std::fill_n(this->level_generator._roomMap, 169, -1); + std::fill_n(this->level_generator._blockedPositions, 169, false); + this->level_generator._isChapter6 = false; + this->level_generator._isStageVoid = false; + this->level_generator._isXL = false; } -bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shape, int doors) { - RoomCoords base_coords(col, row); - if (!base_coords.IsValid()) { +bool DungeonGenerator::CanRoomBePlaced(XY& base_coords, int shape, int allowed_doors, bool allow_unconnected) { + int base_grid_index = base_coords.ToGridIdx(); + if (!this->level_generator.IsPositionInBounds(base_coords)) { return false; } - std::vector occupied_coords = GetOccupiedCoords(base_coords, room_shape); - for (RoomCoords coords : occupied_coords) { - if (!coords.IsValid()) { - return false; - } - - int gridIndex = coords.ToGridIndex(); + if (!this->level_generator.is_pos_free(&base_coords, shape)) { + return false; + } - if (this->occupied_grid_indexes[gridIndex] || this->forbidden_grid_indexes[gridIndex]) { + if (!allow_unconnected) { + if (!this->level_generator.is_placement_valid((unsigned int*)&base_grid_index, shape)) { return false; } } - std::vector forbidden_coords = GetForbiddenNeighbors(base_coords, room_shape, doors); - for (RoomCoords coords : forbidden_coords) { - int gridIndex = coords.ToGridIndex(); - - if (this->occupied_grid_indexes[gridIndex]) { + std::vector forbbidden_neighbors = GetForbiddenNeighbors(base_coords, shape, allowed_doors); + for (XY coords : forbbidden_neighbors) { + int grid_index = coords.ToGridIdx(); + if (this->level_generator._roomMap[grid_index] > -1) { return false; } } @@ -71,29 +82,28 @@ bool DungeonGenerator::CanRoomBePlaced(uint32_t col, uint32_t row, int room_shap return true; } -void DungeonGenerator::FillOccupiedAndForbiddenIndexes(uint32_t row, uint32_t col, int shape, int doors) { - RoomCoords coords(col, row); - - std::vector occupied_coords = GetOccupiedCoords(coords, shape); - for (RoomCoords coords : occupied_coords) { - this->occupied_grid_indexes.set(coords.ToGridIndex()); - } - - std::vector forbidden_coords = GetForbiddenNeighbors(coords, shape, doors); - for (RoomCoords coords : forbidden_coords) { - this->forbidden_grid_indexes.set(coords.ToGridIndex()); +void DungeonGenerator::BlockPositionsFromAllowedDoords(XY& base_coords, int shape, int allowed_doors) { + std::vector forbbidden_neighbors = GetForbiddenNeighbors(base_coords, shape, allowed_doors); + for (XY coords : forbbidden_neighbors) { + this->level_generator.BlockPosition(coords); } } DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, uint32_t col, uint32_t row, int doors) { - int new_room_list_index = this->num_rooms; + LevelGenerator_Room level_generator_room; + level_generator_room._gridColIdx = col; + level_generator_room._gridLineIdx = row; + level_generator_room._shape = room_config->Shape; + bool result = this->level_generator.place_room(&level_generator_room); + + LevelGenerator_Room placed_room = this->level_generator._rooms.at(this->level_generator._rooms.size() - 1); + + int new_room_list_index = placed_room._generationIndex; this->rooms[new_room_list_index] = DungeonGeneratorRoom(new_room_list_index, room_config, col, row, doors); this->num_rooms++; DungeonGeneratorRoom* generatorRoom = &this->rooms[new_room_list_index]; - FillOccupiedAndForbiddenIndexes(row, col, room_config->Shape, doors); - return generatorRoom; } @@ -118,36 +128,44 @@ void DungeonGenerator::CleanFloor(Level* level) { g_Game->_nbRooms = 0; } -void DungeonGenerator::PlaceRoomsInFloor() { - for (int i = 0; i < this->num_rooms; i++) +bool DungeonGenerator::PlaceRoomsInFloor() { + this->level_generator.calc_required_doors(); + + for (LevelGenerator_Room room : this->level_generator._rooms) { - DungeonGeneratorRoom generator_room = this->rooms[i]; + DungeonGeneratorRoom generator_room = this->rooms[room._generationIndex]; + RoomConfig_Room* room_config = generator_room.GetRoomConfig(this->rng->Next(), room._doors); - if (generator_room.room != nullptr) { - LevelGenerator_Room level_generator_room; - level_generator_room._gridColIdx = generator_room.col; - level_generator_room._gridLineIdx = generator_room.row; - level_generator_room._doors = generator_room.doors; + if (room_config == nullptr) { + return false; + } - uint32_t seed = this->rng->Next(); + uint32_t seed = this->rng->Next(); - g_Game->PlaceRoom(&level_generator_room, generator_room.room, seed, 0); - } + g_Game->PlaceRoom(&room, room_config, seed, 0); } g_Game->_lastBossRoomListIdx = this->final_boss_index; + + return true; } bool DungeonGenerator::Generate(Level* level) { if (!this->ValidateFloor()) { + KAGE::_LogMessage(1, "[WARN] Failed to validate custom floor, not placing rooms.\n"); + return false; } CleanFloor(level); - PlaceRoomsInFloor(); + bool could_place_rooms = PlaceRoomsInFloor(); + if (!could_place_rooms) { + KAGE::_LogMessage(1, "[WARN] Couldn't place the rooms in the level, clearing placed rooms...\n"); + CleanFloor(level); + } - return true; + return could_place_rooms; } #pragma endregion @@ -161,13 +179,15 @@ LUA_FUNCTION(Lua_PlaceRoom) { RoomConfig_Room* config = lua::GetLuabridgeUserdata(L, 2, lua::Metatables::CONST_ROOM_CONFIG_ROOM, "RoomConfig"); uint32_t col = (uint32_t)luaL_checkinteger(L, 3); uint32_t row = (uint32_t)luaL_checkinteger(L, 4); - int doors = (int)luaL_optinteger(L, 5, 255); + int allowed_doors = (int)luaL_optinteger(L, 5, 255); // Can't have more doors than what the config allows. - doors = doors & config->Doors; + allowed_doors = allowed_doors & config->Doors; - if (generator->CanRoomBePlaced(col, row, config->Shape, doors)) { - DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row, doors); + XY coords(col, row); + + if (generator->CanRoomBePlaced(coords, config->Shape, allowed_doors, true)) { + DungeonGeneratorRoom* generator_room = generator->PlaceRoom(config, col, row, allowed_doors); DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); *ud = generator_room; @@ -187,9 +207,9 @@ LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { uint32_t col = 6; uint32_t row = 6; - KAGE::_LogMessage(0, "[SEX] dungeon %d\n", doors); + XY coords(col, row); - if (generator->CanRoomBePlaced(col, row, ROOMSHAPE_1x1, doors)) { + if (generator->CanRoomBePlaced(coords, ROOMSHAPE_1x1, doors, true)) { int required_doors = 0; RoomConfig* room_config = g_Game->GetRoomConfig(); diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 02a11a1aa..913b91e5e 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -21,12 +21,15 @@ struct DungeonGeneratorRoom { DungeonGeneratorRoom(); DungeonGeneratorRoom(int list_index, RoomConfig_Room* room, uint32_t row, uint32_t col, int doors); + + RoomConfig_Room* GetRoomConfig(uint32_t seed, int required_doors); }; struct DungeonGenerator { int num_rooms; DungeonGeneratorRoom rooms[169]; RNG* rng; + LevelGenerator level_generator; std::bitset<169> occupied_grid_indexes; std::bitset<169> forbidden_grid_indexes; @@ -34,9 +37,9 @@ struct DungeonGenerator { DungeonGenerator(RNG* rng); - bool CanRoomBePlaced(uint32_t row, uint32_t col, int shape, int doors); + bool CanRoomBePlaced(XY& base_coords, int shape, int allowed_doors, bool allow_unconnected); - void FillOccupiedAndForbiddenIndexes(uint32_t row, uint32_t col, int shape, int doors); + void BlockPositionsFromAllowedDoords(XY& base_coords, int shape, int allowed_doors); DungeonGeneratorRoom* PlaceRoom(RoomConfig_Room* room_config, uint32_t row, uint32_t col, int doors); @@ -46,7 +49,7 @@ struct DungeonGenerator { void CleanFloor(Level* level); - void DungeonGenerator::PlaceRoomsInFloor(); + bool DungeonGenerator::PlaceRoomsInFloor(); bool Generate(Level* level); }; \ No newline at end of file diff --git a/repentogon/Utils/LevelGenUtils.cpp b/repentogon/Utils/LevelGenUtils.cpp index 6a729c71b..7566fba4e 100644 --- a/repentogon/Utils/LevelGenUtils.cpp +++ b/repentogon/Utils/LevelGenUtils.cpp @@ -2,74 +2,59 @@ #include #include -#pragma region RoomCoords struct impl - -RoomCoords::RoomCoords(uint32_t col, uint32_t row) { - this->col = col; - this->row = row; -} - -bool RoomCoords::IsValid() const { - return row >= 0 && row <= 13 && col >= 0 && col <= 13; -} - -int RoomCoords::ToGridIndex() const { - return col + row * 13; -} +#pragma region Helpers -bool RoomCoords::operator==(RoomCoords const& other) const { - return this->row == other.row && this->col == other.col; +void PushCoordsIfValid(std::vector& list, XY& coords) { + if (coords.ToGridIdx() >= 0) { + list.push_back(coords); + } } -#pragma endregion - -#pragma region Helpers - -std::vector GetOccupiedCoords(RoomCoords& base_coords, int shape) { - std::vector occupied_coords = {}; +std::vector GetOccupiedCoords(XY& base_coords, int shape) { + std::vector occupied_coords = {}; switch (shape) { case ROOMSHAPE_1x1: case ROOMSHAPE_IH: case ROOMSHAPE_IV: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y)); break; case ROOMSHAPE_1x2: case ROOMSHAPE_IIV: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y + 1)); break; case ROOMSHAPE_2x1: case ROOMSHAPE_IIH: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y)); break; case ROOMSHAPE_2x2: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y + 1)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y + 1)); break; case ROOMSHAPE_LTL: - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y + 1)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y + 1)); break; case ROOMSHAPE_LTR: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y + 1)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y + 1)); break; case ROOMSHAPE_LBL: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y + 1)); break; case ROOMSHAPE_LBR: - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); - occupied_coords.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x + 1, base_coords.y)); + occupied_coords.push_back(XY(base_coords.x, base_coords.y + 1)); break; default: break; @@ -78,225 +63,225 @@ std::vector GetOccupiedCoords(RoomCoords& base_coords, int shape) { return occupied_coords; } -std::vector GetForbiddenNeighbors(RoomCoords& base_coords, int shape, int doors) { - std::vector forbidden_neighbors = {}; +std::vector GetForbiddenNeighbors(XY& base_coords, int shape, int doors) { + std::vector forbidden_neighbors = {}; switch (shape) { case ROOMSHAPE_1x1: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 1)); } break; case ROOMSHAPE_IH: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y)); } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 1)); break; case ROOMSHAPE_IV: - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y)); if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 1)); } break; case ROOMSHAPE_1x2: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 1)); } break; case ROOMSHAPE_IIV: - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y)); if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 1)); } - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 1)); break; case ROOMSHAPE_2x1: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 1)); } break; case ROOMSHAPE_IIH: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y)); } - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 1)); break; case ROOMSHAPE_2x2: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 2)); } break; case ROOMSHAPE_LTL: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0 || (doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 2)); } break; case ROOMSHAPE_LTR: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0 || (doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 2)); } break; case ROOMSHAPE_LBL: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0 || (doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 2)); } break; case ROOMSHAPE_LBR: if ((doors & (1 << DOOR_SLOT_LEFT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_UP0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 2, base_coords.row)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 2, base_coords.y)); } if ((doors & (1 << DOOR_SLOT_DOWN0)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col, base_coords.row + 2)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x, base_coords.y + 2)); } if ((doors & (1 << DOOR_SLOT_LEFT1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col - 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x - 1, base_coords.y + 1)); } if ((doors & (1 << DOOR_SLOT_UP1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row - 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y - 1)); } if ((doors & (1 << DOOR_SLOT_RIGHT1)) == 0 || (doors & (1 << DOOR_SLOT_DOWN1)) == 0) { - forbidden_neighbors.push_back(RoomCoords(base_coords.col + 1, base_coords.row + 1)); + PushCoordsIfValid(forbidden_neighbors, XY(base_coords.x + 1, base_coords.y + 1)); } break; default: diff --git a/repentogon/Utils/LevelGenUtils.h b/repentogon/Utils/LevelGenUtils.h index 2e4999966..8be4f0e6f 100644 --- a/repentogon/Utils/LevelGenUtils.h +++ b/repentogon/Utils/LevelGenUtils.h @@ -1,20 +1,8 @@ #pragma once #include #include +#include -struct RoomCoords { - uint32_t col; - uint32_t row; +std::vector GetOccupiedCoords(XY& base_coords, int shape); - RoomCoords(uint32_t col, uint32_t row); - - bool IsValid() const; - - int ToGridIndex() const; - - bool operator==(RoomCoords const& other) const; -}; - -std::vector GetOccupiedCoords(RoomCoords& base_coords, int shape); - -std::vector GetForbiddenNeighbors(RoomCoords& base_coords, int shape, int doors); \ No newline at end of file +std::vector GetForbiddenNeighbors(XY& base_coords, int shape, int doors); \ No newline at end of file From 2c3719195a66dbf9060f45856073bc5f2458640b Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Mon, 10 Nov 2025 18:40:30 +0100 Subject: [PATCH 32/35] Removed ununsed fields --- repentogon/LuaInterfaces/LuaDungeonGenerator.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 913b91e5e..49902e6ec 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -30,8 +30,6 @@ struct DungeonGenerator { DungeonGeneratorRoom rooms[169]; RNG* rng; LevelGenerator level_generator; - std::bitset<169> occupied_grid_indexes; - std::bitset<169> forbidden_grid_indexes; int final_boss_index = -1; From 86ff2bb314ae5bf05f2d77b8ed4251c6441547a2 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Tue, 11 Nov 2025 17:04:08 +0100 Subject: [PATCH 33/35] Added BlockIndex function --- repentogon/LuaInterfaces/LuaDungeonGenerator.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index f31a6b20f..e0be73d82 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -210,7 +210,7 @@ LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { XY coords(col, row); if (generator->CanRoomBePlaced(coords, ROOMSHAPE_1x1, doors, true)) { - int required_doors = 0; + unsigned int required_doors = 0; RoomConfig* room_config = g_Game->GetRoomConfig(); RoomConfig_Room* config = room_config->GetRandomRoom( @@ -223,7 +223,7 @@ LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { 2, 0, 10, - (unsigned int*)&required_doors, // If I don't do it like this it shits itself + &required_doors, // If I don't do it like this it shits itself 0, -1 ); @@ -241,7 +241,6 @@ LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { } } - LUA_FUNCTION(Lua_SetFinalBossRoom) { DungeonGenerator* generator = GetDungeonGenerator(L); DungeonGeneratorRoom* generator_room = *lua::GetRawUserdata(L, 2, lua::metatables::DungeonGeneratorRoomMT); @@ -251,11 +250,22 @@ LUA_FUNCTION(Lua_SetFinalBossRoom) { return 0; } +LUA_FUNCTION(Lua_BlockIndex) { + DungeonGenerator* generator = GetDungeonGenerator(L); + int grid_index = (int)luaL_checkinteger(L, 2); + + generator->level_generator.BlockPosition(grid_index); + + return 0; +} + + static void RegisterDungeonGenerator(lua_State* L) { luaL_Reg functions[] = { {"PlaceRoom", Lua_PlaceRoom}, {"SetFinalBossRoom", Lua_SetFinalBossRoom}, {"PlaceDefaultStartingRoom", Lua_PlaceDefaultStartingRoom}, + {"BlockIndex", Lua_BlockIndex}, { NULL, NULL } }; From 062d1570b9737db563919daa560814b4d66cebf7 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Tue, 11 Nov 2025 17:05:16 +0100 Subject: [PATCH 34/35] Changed optional return --- repentogon/LuaInterfaces/LuaDungeonGenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index e0be73d82..6473d55b2 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -233,12 +233,12 @@ LUA_FUNCTION(Lua_PlaceDefaultStartingRoom) { DungeonGeneratorRoom** ud = (DungeonGeneratorRoom**)lua_newuserdata(L, sizeof(DungeonGeneratorRoom*)); *ud = generator_room; luaL_setmetatable(L, lua::metatables::DungeonGeneratorRoomMT); - - return 1; } else { - return 0; + lua_pushnil(L); } + + return 1; } LUA_FUNCTION(Lua_SetFinalBossRoom) { From 47327795dd608f69059f254569bbbaafbf9bfb64 Mon Sep 17 00:00:00 2001 From: thicco-catto Date: Tue, 11 Nov 2025 19:27:23 +0100 Subject: [PATCH 35/35] Added custom callback logic --- repentogon/LuaInterfaces/CustomCallbacks.cpp | 4 +- .../LuaInterfaces/LuaDungeonGenerator.cpp | 76 ++++++++++++++++--- .../LuaInterfaces/LuaDungeonGenerator.h | 12 ++- repentogon/resources/scripts/main_ex.lua | 16 ++++ 4 files changed, 92 insertions(+), 16 deletions(-) diff --git a/repentogon/LuaInterfaces/CustomCallbacks.cpp b/repentogon/LuaInterfaces/CustomCallbacks.cpp index b582460b7..6ba570f9a 100644 --- a/repentogon/LuaInterfaces/CustomCallbacks.cpp +++ b/repentogon/LuaInterfaces/CustomCallbacks.cpp @@ -5661,7 +5661,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG& rng, DungeonGenerationTyp lua::LuaStackProtector protector(L); lua_rawgeti(L, LUA_REGISTRYINDEX, g_LuaEngine->runCallbackRegistry->key); - DungeonGenerator generator(&rng); + DungeonGenerator generator(&rng, level); lua::LuaResults results = lua::LuaCaller(L) .push(callbackId) .push((int)dungeonType) @@ -5675,7 +5675,7 @@ bool ProcessGenerateDungeonCallback(Level* level, RNG& rng, DungeonGenerationTyp return false; } - bool correctGeneration = generator.Generate(level); + bool correctGeneration = generator.Generate(); return correctGeneration; } diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp index 6473d55b2..3b19865c4 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.cpp @@ -43,16 +43,15 @@ RoomConfig_Room* DungeonGeneratorRoom::GetRoomConfig(uint32_t seed, int required #pragma region DungeonGenerator Impl -DungeonGenerator::DungeonGenerator(RNG* rng) { - this->num_rooms = 0; +DungeonGenerator::DungeonGenerator(RNG* rng, Level* level) { this->rng = rng; + this->level = level; this->level_generator._rng = *rng; - std::fill_n(this->level_generator._roomMap, 169, -1); - std::fill_n(this->level_generator._blockedPositions, 169, false); this->level_generator._isChapter6 = false; this->level_generator._isStageVoid = false; this->level_generator._isXL = false; + this->ResetLevelGenerator(); } bool DungeonGenerator::CanRoomBePlaced(XY& base_coords, int shape, int allowed_doors, bool allow_unconnected) { @@ -101,7 +100,6 @@ DungeonGeneratorRoom* DungeonGenerator::PlaceRoom(RoomConfig_Room* room_config, int new_room_list_index = placed_room._generationIndex; this->rooms[new_room_list_index] = DungeonGeneratorRoom(new_room_list_index, room_config, col, row, doors); - this->num_rooms++; DungeonGeneratorRoom* generatorRoom = &this->rooms[new_room_list_index]; return generatorRoom; @@ -114,11 +112,29 @@ void DungeonGenerator::SetFinalBossRoom(DungeonGeneratorRoom* boss_room) { bool DungeonGenerator::ValidateFloor() { bool has_final_room = this->final_boss_index >= 0; + // Check if all rooms can fetch a room config + int initial_seed = this->rng->_seed; + + for (LevelGenerator_Room room : this->level_generator._rooms) + { + DungeonGeneratorRoom generator_room = this->rooms[room._generationIndex]; + RoomConfig_Room* room_config = generator_room.GetRoomConfig(this->rng->Next(), room._doors); + + if (room_config == nullptr) { + return false; + } + + // When placing the rooms the rng is advanced here too. + this->rng->Next(); + } + + this->rng->_seed = initial_seed; + return has_final_room; } -void DungeonGenerator::CleanFloor(Level* level) { - level->reset_room_list(false); +void DungeonGenerator::CleanFloor() { + this->level->reset_room_list(false); for (size_t i = 0; i < 507; i++) { @@ -128,6 +144,25 @@ void DungeonGenerator::CleanFloor(Level* level) { g_Game->_nbRooms = 0; } +void DungeonGenerator::ResetLevelGenerator() { + std::fill_n(this->level_generator._roomMap, 169, -1); + std::fill_n(this->level_generator._blockedPositions, 169, false); + + this->level_generator._rooms.clear(); +} + +void DungeonGenerator::Reset() { + this->CleanFloor(); + + this->ResetLevelGenerator(); + + this->final_boss_index = -1; + for (size_t i = 0; i < 169; i++) + { + this->rooms[i] = DungeonGeneratorRoom(); + } +} + bool DungeonGenerator::PlaceRoomsInFloor() { this->level_generator.calc_required_doors(); @@ -150,19 +185,20 @@ bool DungeonGenerator::PlaceRoomsInFloor() { return true; } -bool DungeonGenerator::Generate(Level* level) { +bool DungeonGenerator::Generate() { if (!this->ValidateFloor()) { KAGE::_LogMessage(1, "[WARN] Failed to validate custom floor, not placing rooms.\n"); + Reset(); return false; } - CleanFloor(level); + CleanFloor(); bool could_place_rooms = PlaceRoomsInFloor(); if (!could_place_rooms) { KAGE::_LogMessage(1, "[WARN] Couldn't place the rooms in the level, clearing placed rooms...\n"); - CleanFloor(level); + Reset(); } return could_place_rooms; @@ -259,6 +295,24 @@ LUA_FUNCTION(Lua_BlockIndex) { return 0; } +LUA_FUNCTION(Lua_Validate) { + DungeonGenerator* generator = GetDungeonGenerator(L); + + bool result = generator->ValidateFloor(); + + lua_pushboolean(L, result); + + return 1; +} + +LUA_FUNCTION(Lua_Reset) { + DungeonGenerator* generator = GetDungeonGenerator(L); + + generator->Reset(); + + return 0; +} + static void RegisterDungeonGenerator(lua_State* L) { luaL_Reg functions[] = { @@ -266,6 +320,8 @@ static void RegisterDungeonGenerator(lua_State* L) { {"SetFinalBossRoom", Lua_SetFinalBossRoom}, {"PlaceDefaultStartingRoom", Lua_PlaceDefaultStartingRoom}, {"BlockIndex", Lua_BlockIndex}, + {"Validate", Lua_Validate}, + {"Reset", Lua_Reset}, { NULL, NULL } }; diff --git a/repentogon/LuaInterfaces/LuaDungeonGenerator.h b/repentogon/LuaInterfaces/LuaDungeonGenerator.h index 49902e6ec..f6a131aac 100644 --- a/repentogon/LuaInterfaces/LuaDungeonGenerator.h +++ b/repentogon/LuaInterfaces/LuaDungeonGenerator.h @@ -26,14 +26,14 @@ struct DungeonGeneratorRoom { }; struct DungeonGenerator { - int num_rooms; DungeonGeneratorRoom rooms[169]; RNG* rng; + Level* level; LevelGenerator level_generator; int final_boss_index = -1; - DungeonGenerator(RNG* rng); + DungeonGenerator(RNG* rng, Level* level); bool CanRoomBePlaced(XY& base_coords, int shape, int allowed_doors, bool allow_unconnected); @@ -45,9 +45,13 @@ struct DungeonGenerator { bool ValidateFloor(); - void CleanFloor(Level* level); + void CleanFloor(); bool DungeonGenerator::PlaceRoomsInFloor(); - bool Generate(Level* level); + bool Generate(); + + void Reset(); + + void ResetLevelGenerator(); }; \ No newline at end of file diff --git a/repentogon/resources/scripts/main_ex.lua b/repentogon/resources/scripts/main_ex.lua index acfbc6a0d..522fcd9ec 100644 --- a/repentogon/resources/scripts/main_ex.lua +++ b/repentogon/resources/scripts/main_ex.lua @@ -1687,6 +1687,21 @@ local function RunPreStatusEffectApplyCallback(callbackID, param, status, entity return recentRet end +local function RunPreGenerateDungeonCallback(callbackID, param, dungeonGenerator, rng, dungeonType) + for callback in GetCallbackIterator(callbackID, param) do + local ret = RunCallbackInternal(callbackID, callback, dungeonGenerator, rng, dungeonType) + + if type(ret) == "boolean" and ret then + local canGenerate = dungeonGenerator:Validate() + if canGenerate then + return true + else + dungeonGenerator:Reset() + end + end + end +end + -- I don't think we need these exposed anymore, but safer to just leave them alone since they were already exposed. rawset(Isaac, "RunPreRenderCallback", _RunPreRenderCallback) rawset(Isaac, "RunAdditiveCallback", _RunAdditiveCallback) @@ -1728,6 +1743,7 @@ local CustomRunCallbackLogic = { [ModCallbacks.MC_PRE_ADD_TRINKET] = RunPreAddTrinketCallback, [ModCallbacks.MC_POST_ADD_COLLECTIBLE] = RunNoReturnCallback, [ModCallbacks.MC_PLAYER_GET_HEART_LIMIT] = RunAdditiveSecondArgCallback, + [ModCallbacks.MC_PRE_GENERATE_DUNGEON] = RunPreGenerateDungeonCallback } for _, callback in ipairs({