Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I guess we're doing UI again #345

Merged
merged 32 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
43fc95c
add levelgen flags
Dregu Oct 8, 2023
6767fa8
Merge branch 'main' into UI
Dregu Oct 11, 2023
b166e9f
Use destroy_grid in ui delete
Dregu Oct 11, 2023
ff63713
hitbox color fixes
Dregu Oct 11, 2023
3be15a4
Merge branch 'main' into UI
Dregu Oct 11, 2023
2dd67d9
add ui warp buttons to special game screens
Dregu Oct 11, 2023
26e3165
Add unload level callbacks
Dregu Oct 11, 2023
eeeeabf
rename unload_level and add pre_spawn_level
Dregu Oct 11, 2023
fdfd1ad
layer init hooks
Dregu Oct 11, 2023
0c3b6c7
add set_death_enabled
Dregu Oct 11, 2023
28337d4
add ui options to disable death and respawn players
Dregu Oct 11, 2023
6560ecb
Merge branch 'main' into UI
Dregu Oct 12, 2023
0e3294e
fix get_procedural_chance logic
Dregu Oct 12, 2023
c19bb9d
add procedural chances to ui
Dregu Oct 12, 2023
646a07b
ui chances fixes
Dregu Oct 12, 2023
e70b5cb
thank you for the useless warning
Dregu Oct 12, 2023
54a993a
run level gen callbacks for transitions
Dregu Oct 12, 2023
a312d78
testing cutscene_behavior
Dregu Oct 13, 2023
f3cdf00
fix spawn_player position
Dregu Oct 13, 2023
a9c1f3e
add layer hack to spawn_player
Dregu Oct 13, 2023
20eeb43
uglier hack that works better
Dregu Oct 14, 2023
07f6968
make it not stupid
Dregu Oct 14, 2023
a449568
remove defaults
Dregu Oct 14, 2023
5425ab7
fix docs
Dregu Oct 14, 2023
3b62a27
add patterns for new patterns
Dregu Oct 14, 2023
55584e9
fix clear_callback in movable virtual hooks
Dregu Oct 14, 2023
0aedff0
change some patterns to vtable offsets
Dregu Oct 14, 2023
27df88c
fix spawn_player uid
Dregu Oct 14, 2023
2fd3f4b
update docs
Dregu Oct 14, 2023
d375795
remove cutscenes, add some input helpers
Dregu Oct 14, 2023
1a100fd
fix crash when destroying layer with players
Dregu Oct 14, 2023
56a7322
rename and document death
Dregu Oct 14, 2023
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
51 changes: 51 additions & 0 deletions src/game_api/flags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,3 +756,54 @@ const char* pause_types[]{
"32: Ankh (smooth camera, janky audio)",
"Freeze on PRE_UPDATE", // this is not a real state.pause flag, it's only used by ui.cpp for magic
};

const char* levelgen_flags[]{
"1: Should generate path",
"2: Can spawn vault",
"3: Can spawn shops",
"4: Can have outpost?",
"5: Should spawn hard floor decorations",
"6: Apply ambient occlusion",
"7: Should spawn behind-floor and below-floorstyled decorations",
"8: unknown",
};

const char* levelgen_flags2[]{
"1: Spawns background decorations on ground (ceiling if false)",
"2: Spawns fake ladder/chain midbg?",
"3: Spawn entrance door background (Ignored in 7-1 to 7-2 transition)",
"4: Procedural backlayer door midbg indicator related",
"5: Spawn backlayer border/background",
"6: Should spawn procedural backlayers",
"7: Should spawn backlayer torches",
"8: Has ghost",
};

const char* levelgen_flags3[]{
"1: Can spawn angry NPCs",
"2: Can echo",
"3: Can spawn Dead are Restless",
"4: Can spawn procedural skeletons",
"5: Can have quests?",
"6: Can spawn player coffins",
"7: unknown",
"8: unknown",
};

const char* level_chances[]{
"backroom",
"backroom interconnect",
"backroom hidden door",
"backroom hidden cache",
"mount",
"altar",
"idol",
"floor side spread",
"floor bottom spread",
"background",
"ground background",
"bigroom",
"wideroom",
"tallroom",
"rewardroom",
};
127 changes: 120 additions & 7 deletions src/game_api/level_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,8 @@ void level_gen(LevelGenSystem* level_gen_sys, float param_2, size_t param_3)
g_CustomShopTypes[0] = {};
g_CustomShopTypes[1] = {};

pre_level_generation();
if (pre_level_generation())
return;
g_level_gen_trampoline(level_gen_sys, param_2, param_3);
post_level_generation();

Expand All @@ -846,6 +847,62 @@ void level_gen(LevelGenSystem* level_gen_sys, float param_2, size_t param_3)
g_levels_to_load.clear();
}

using TransGenFun = void(ThemeInfo*);
TransGenFun* g_trans_gen_trampoline{nullptr};
TransGenFun* g_trans_gen2_trampoline{nullptr};
using TransGenFun3 = void(size_t, size_t, ThemeInfo*);
TransGenFun3* g_trans_gen3_trampoline{nullptr};
using TransGenFun4 = void(size_t, size_t, size_t, size_t, size_t, size_t);
TransGenFun4* g_trans_gen4_trampoline{nullptr};
// generic transition hook
void trans_gen(ThemeInfo* theme)
{
push_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL);
OnScopeExit pop{[]
{ pop_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL); }};

if (pre_level_generation())
return;
g_trans_gen_trampoline(theme);
post_level_generation();
}
// cosmic transition hook
void trans_gen2(ThemeInfo* theme)
{
push_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL);
OnScopeExit pop{[]
{ pop_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL); }};

if (pre_level_generation())
return;
g_trans_gen2_trampoline(theme);
post_level_generation();
}
// duat transition hook
void trans_gen3(size_t a, size_t b, ThemeInfo* theme)
{
push_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL);
OnScopeExit pop{[]
{ pop_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL); }};

if (pre_level_generation())
return;
g_trans_gen3_trampoline(a, b, theme);
post_level_generation();
}
// olmecship transition hook
void trans_gen4(size_t a, size_t b, size_t c, size_t d, size_t e, size_t f)
{
push_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL);
OnScopeExit pop{[]
{ pop_spawn_type_flags(SPAWN_TYPE_LEVEL_GEN_GENERAL); }};

if (pre_level_generation())
return;
g_trans_gen4_trampoline(a, b, c, d, e, f);
post_level_generation();
}

using LoadScreenFun = void(StateMemory*, size_t, size_t);
LoadScreenFun* g_load_screen_trampoline{nullptr};
void load_screen(StateMemory* state, size_t param_2, size_t param_3)
Expand All @@ -856,6 +913,33 @@ void load_screen(StateMemory* state, size_t param_2, size_t param_3)
post_load_screen();
}

using UnloadLayerFun = void(Layer*);
UnloadLayerFun* g_unload_layer_trampoline{nullptr};
void unload_layer(Layer* layer)
{
if (!layer->is_back_layer && pre_unload_level())
return;
if (pre_unload_layer((LAYER)layer->is_back_layer))
return;
g_unload_layer_trampoline(layer);
post_unload_layer((LAYER)layer->is_back_layer);
if (layer->is_back_layer)
post_unload_level();
}

using InitLayerFun = void(Layer*);
InitLayerFun* g_init_layer_trampoline{nullptr};
void load_layer(Layer* layer)
{
if (!layer->is_back_layer)
pre_init_level();
pre_init_layer((LAYER)layer->is_back_layer);
g_init_layer_trampoline(layer);
post_init_layer((LAYER)layer->is_back_layer);
if (layer->is_back_layer)
post_init_level();
}

using HandleTileCodeFun = void(LevelGenSystem*, std::uint32_t, std::uint64_t, float, float, std::uint8_t);
HandleTileCodeFun* g_handle_tile_code_trampoline{nullptr};
void handle_tile_code(LevelGenSystem* self, std::uint32_t tile_code, std::uint16_t room_template, float x, float y, std::uint8_t layer)
Expand Down Expand Up @@ -1470,6 +1554,12 @@ void LevelGenData::init()
g_spawn_room_from_tile_codes_trampoline = (SpawnRoomFromTileCodes*)get_address("level_gen_spawn_room_from_tile_codes"sv);

g_load_screen_trampoline = (LoadScreenFun*)get_address("load_screen_func"sv);
g_unload_layer_trampoline = (UnloadLayerFun*)get_address("unload_layer"sv);
g_init_layer_trampoline = (InitLayerFun*)get_address("init_layer"sv);
g_trans_gen_trampoline = (TransGenFun*)get_address("spawn_transition"sv);
g_trans_gen2_trampoline = (TransGenFun*)get_address("spawn_transition_cosmic"sv);
g_trans_gen3_trampoline = (TransGenFun3*)get_address("spawn_transition_duat"sv);
g_trans_gen4_trampoline = (TransGenFun4*)get_address("spawn_transition_olmecship"sv);

DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
Expand All @@ -1485,6 +1575,12 @@ void LevelGenData::init()
DetourAttach((void**)&g_spawn_room_from_tile_codes_trampoline, spawn_room_from_tile_codes);

DetourAttach((void**)&g_load_screen_trampoline, load_screen);
DetourAttach((void**)&g_unload_layer_trampoline, unload_layer);
DetourAttach((void**)&g_init_layer_trampoline, load_layer);
DetourAttach((void**)&g_trans_gen_trampoline, trans_gen);
DetourAttach((void**)&g_trans_gen2_trampoline, trans_gen2);
DetourAttach((void**)&g_trans_gen3_trampoline, trans_gen3);
DetourAttach((void**)&g_trans_gen4_trampoline, trans_gen4);

const LONG error = DetourTransactionCommit();
if (error != NO_ERROR)
Expand Down Expand Up @@ -1949,6 +2045,15 @@ LevelChanceDef& get_or_emplace_level_chance(game_unordered_map<std::uint32_t, Le
return node.first->value.second;
}

std::optional<std::string_view> LevelGenSystem::get_procedural_spawn_chance_name(uint32_t chance_id)
{
if (g_monster_chance_id_to_name.contains(chance_id))
return g_monster_chance_id_to_name[chance_id];
if (g_trap_chance_id_to_name.contains(chance_id))
return g_trap_chance_id_to_name[chance_id];
return std::nullopt;
}

uint32_t LevelGenSystem::get_procedural_spawn_chance(uint32_t chance_id)
{
if (g_monster_chance_id_to_name.contains(chance_id))
Expand All @@ -1957,14 +2062,18 @@ uint32_t LevelGenSystem::get_procedural_spawn_chance(uint32_t chance_id)
if (!this_chances.chances.empty())
{
auto* state = State::get().ptr();
if (this_chances.chances.size() >= state->level)
if (this_chances.chances.size() >= state->level && state->level > 0)
{
return this_chances.chances[state->level];
return this_chances.chances[state->level - 1];
}
else
else if (this_chances.chances.size() == 1)
{
return this_chances.chances[0];
}
else
{
return 0;
}
}
}

Expand All @@ -1974,14 +2083,18 @@ uint32_t LevelGenSystem::get_procedural_spawn_chance(uint32_t chance_id)
if (!this_chances.chances.empty())
{
auto* state = State::get().ptr();
if (this_chances.chances.size() >= state->level)
if (this_chances.chances.size() >= state->level && state->level > 0)
{
return this_chances.chances[state->level];
return this_chances.chances[state->level - 1];
}
else
else if (this_chances.chances.size() == 1)
{
return this_chances.chances[0];
}
else
{
return 0;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/game_api/level_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ struct LevelGenSystem
bool set_shop_type(uint32_t x, uint32_t y, uint8_t l, ShopType shop_type);

std::string_view get_room_template_name(uint16_t room_template);

std::optional<std::string_view> get_procedural_spawn_chance_name(uint32_t chance_id);
uint32_t get_procedural_spawn_chance(uint32_t chance_id);
bool set_procedural_spawn_chance(uint32_t chance_id, uint32_t inverse_chance);

Expand Down
4 changes: 2 additions & 2 deletions src/game_api/movable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class CutsceneBehavior
{
public:
virtual ~CutsceneBehavior(){};
virtual void update() = 0;
virtual void update(Movable* e) = 0;
// no more virtuals, it's possible that different sub classes have some extra variables as well
};

Expand All @@ -24,7 +24,7 @@ class Movable : public Entity
custom_map<uint32_t, MovableBehavior*> behaviors_map;
custom_set<MovableBehavior*, SortMovableBehavior> behaviors;
MovableBehavior* current_behavior;
CutsceneBehavior* ic8;
CutsceneBehavior* cutscene_behavior;
union
{
/// {movex, movey}
Expand Down
60 changes: 60 additions & 0 deletions src/game_api/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2142,3 +2142,63 @@ std::optional<double> get_frametime_inactive()
return memory_read<double>(offset);
return std::nullopt;
}

void destroy_layer(uint8_t layer)
{
static size_t offset = 0;
if (offset == 0)
{
offset = get_address("unload_layer");
}
if (offset != 0)
{
auto* layer_ptr = State::get().layer(layer);
typedef void destroy_func(Layer*);
static destroy_func* df = (destroy_func*)(offset);
df(layer_ptr);
}
}

void destroy_level()
{
destroy_layer(0);
destroy_layer(1);
}

void create_layer(uint8_t layer)
{
static size_t offset = 0;
if (offset == 0)
{
offset = get_address("init_layer");
}
if (offset != 0)
{
auto* layer_ptr = State::get().layer(layer);
typedef void init_func(Layer*);
static init_func* ilf = (init_func*)(offset);
ilf(layer_ptr);
}
}

void create_level()
{
create_layer(0);
create_layer(1);
}

void set_death_enabled(bool enable)
{
static size_t offset = 0;
if (offset == 0)
{
offset = get_address("dead_players");
}
if (offset != 0)
{
if (!enable)
write_mem_recoverable("death_disable", offset, "\xC3\x90"sv, true);
else
recover_mem("death_disable");
}
}
5 changes: 5 additions & 0 deletions src/game_api/rpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,8 @@ void set_frametime(std::optional<double> frametime);
std::optional<double> get_frametime();
void set_frametime_inactive(std::optional<double> frametime);
std::optional<double> get_frametime_inactive();
void destroy_layer(uint8_t layer);
void destroy_level();
void create_layer(uint8_t layer);
void create_level();
void set_death_enabled(bool enable);
Loading
Loading