Skip to content
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8b17521
Reset room list function
thicco-catto Nov 2, 2025
7c047e1
Added bool parameter
thicco-catto Nov 2, 2025
ea8320c
Added callback enum
thicco-catto Nov 2, 2025
d2bf067
Merge branch 'TeamREPENTOGON:main' into level-gen
thicco-catto Nov 3, 2025
2490b78
Added RNG parameter to callback
thicco-catto Nov 3, 2025
8f8c157
Added dungeon generator controller
thicco-catto Nov 4, 2025
f9fb019
Removed test functions and fixed final boss not set
thicco-catto Nov 4, 2025
f65b5f5
Callback triggers for more dungeon types
thicco-catto Nov 4, 2025
d313242
Filter by generation type
thicco-catto Nov 4, 2025
e2f77b4
Moved custom callback to appropiate file
thicco-catto Nov 5, 2025
32e508d
Fixed return values for lua functions
thicco-catto Nov 5, 2025
1feba7f
Renamed lua functions
thicco-catto Nov 5, 2025
bfab985
PlaceRoom returns the room
thicco-catto Nov 6, 2025
845072c
Generator returns bool
thicco-catto Nov 6, 2025
c2cc975
Dungeon generator has own RNG
thicco-catto Nov 7, 2025
47dbdd9
Refactored floor generation
thicco-catto Nov 7, 2025
7d5ce08
Moved implementations to source file
thicco-catto Nov 7, 2025
57a718d
Added room shape check and swapped col/row
thicco-catto Nov 7, 2025
05c839a
Added door validation
thicco-catto Nov 7, 2025
9a7e37e
Added shape field to DungeonGeneratorRoom
thicco-catto Nov 7, 2025
40605fd
Added PlaceDefaultStartingRoom
thicco-catto Nov 7, 2025
797a52d
Fixed constructors
thicco-catto Nov 7, 2025
8ad7897
Added dungeon type param to callback
thicco-catto Nov 7, 2025
2e6f9f4
Changed some pointers to references
thicco-catto Nov 7, 2025
e1b7d98
Changed resetLilPortalRoom param
thicco-catto Nov 8, 2025
bd2415e
Removed unnecesary include
thicco-catto Nov 8, 2025
52c50b5
Use bitset to check room placement
thicco-catto Nov 8, 2025
c308a3e
Created utils file and generation type enum
thicco-catto Nov 8, 2025
0bbb155
Enum is passed as number to callback
thicco-catto Nov 8, 2025
d89ff98
DungeonGenerator now holds index for final boss
thicco-catto Nov 8, 2025
fc5098b
Removed some debug logs
thicco-catto Nov 8, 2025
6edd184
Refactored DungeonGenerator to use LevelGenerator
thicco-catto Nov 9, 2025
2c37191
Removed ununsed fields
thicco-catto Nov 10, 2025
86ff2bb
Added BlockIndex function
thicco-catto Nov 11, 2025
062d157
Changed optional return
thicco-catto Nov 11, 2025
4732779
Added custom callback logic
thicco-catto Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libzhl/LuaCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,8 @@ namespace lua {
const char* LootListEntryMT = "LootListEntry";
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) {
Expand Down
2 changes: 2 additions & 0 deletions libzhl/LuaCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ 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;
extern LIBZHL_API const char* DungeonGeneratorRoomMT;
}

LIBZHL_API void UnloadMetatables();
Expand Down
20 changes: 19 additions & 1 deletion libzhl/functions/Level.zhl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
__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 resetLilPortalRoom);

"558bec6aff68????????64a1????????5083ec2c535657a1????????33c5508d45??64a3????????8bd98b45":
__thiscall void Level::ChangeRoom(int targetRoomIDX, int dimension);

Expand Down Expand Up @@ -61,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);

Expand Down
87 changes: 87 additions & 0 deletions repentogon/LuaInterfaces/CustomCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -5646,4 +5647,90 @@ 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, DungeonGenerationType 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(&rng);
lua::LuaResults results = lua::LuaCaller(L)
.push(callbackId)
.push((int)dungeonType)
.push(&generator, lua::metatables::DungeonGeneratorMT)
.push(&rng, lua::Metatables::RNG)
.push((int)dungeonType)
.call(1);

if (results || !lua_isboolean(L, -1) || !lua_toboolean(L, -1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to change this, as right now I expect that if someone returns an invalid level layout, we don't give a chance for other callbacks to run and simply return to default generation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here seems like it might be fine, but yeah this callback will likely require custom handling in main_ex.lua. We could potentially detect that a mod left things in an invalid state, possibly print an error to the console, then reset it before we run the next callback.

Not mandatory for an initial push, but is something we should sort out before this gets included in a release.

{
return false;
}

bool correctGeneration = generator.Generate(level);

return correctGeneration;
}

HOOK_METHOD(Level, generate_dungeon, (RNG* rng) -> void)
{
bool skip = ProcessGenerateDungeonCallback(this, *rng, DEFAULT);
if (skip) {
return;
}

super(rng);
}

HOOK_METHOD(Level, generate_blue_womb, () -> void) {
bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, BLUE_WOMB);
if (skip) {
return;
}

super();
}

HOOK_METHOD(Level, generate_backwards_dungeon, () -> void) {
bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, BACKWARDS);
if (skip) {
return;
}

super();
}

HOOK_METHOD(Level, generate_home_dungeon, () -> void) {
bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, HOME);
if (skip) {
return;
}

super();
}

HOOK_METHOD(Level, generate_redkey_dungeon, () -> void) {
bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, RED_REDEMPTION);
if (skip) {
return;
}

super();
}

HOOK_METHOD(Level, generate_greed_dungeon, () -> void) {
bool skip = ProcessGenerateDungeonCallback(this, g_Game->_generationRNG, GREED);
if (skip) {
return;
}

super();
}
Loading