spelunky-fyi / overlunky

An overlay for Spelunky 2 to help you with modding, exploring the depths of the game and practicing with tools like spawning arbitrary items, warping to levels and teleporting.
MIT License
86 stars 32 forks source link

Patching the game code to fix crashes #331

Closed Mr-Auto closed 1 year ago

Mr-Auto commented 1 year ago

Patching crashes when:

Mr-Auto commented 1 year ago

I assume we want them active depending on user settings? or should i just put them together with the hooks init stuff?

Dregu commented 1 year ago

I think these kind of patches that have no effect on the vanilla game should just be enabled always when the api is initialized, so not in PL speedrun mode but otherwise automatically.

Dregu commented 1 year ago

I guess it would be perfect that the cutscene never even tries to play if olmec never spawned. And the same for tiamat. I tried the hack with this addition in ui_util.cpp and looks like it worked great even for deleting olmec during the cutscene:

            if (check && in_array(check->type->id, olmecs))
            {
                patch_olmec_kill_crash();
                auto state = State::get().ptr();
                if (state->logic->olmec_cutscene)
                {
                    // if cutscene is still running, perform the last frame of cutscene before killing olmec
                    state->logic->olmec_cutscene->timer = 809;
                    state->logic->olmec_cutscene->perform();
                    state->logic->olmec_cutscene = nullptr;
                }
                destroy_entity_items(check);
                check->destroy();
                return;
            }
Mr-Auto commented 1 year ago

The issue comes down to ability to skip/disable cutscenes which i think would be a good option in itself

Dregu commented 1 year ago

Well I suppose we do have that option already, since the cutscenes are initialized by the spawn_effects theme functions, but those do a lot of things...

Dregu commented 1 year ago

And the game still crashes even if the virtual is disabled but olmec is also disabled.

Mr-Auto commented 1 year ago

ok, i have a kind of working code, the issue is, if i nuke the whole function that set's up the cutscene and logic the camera bounds are f***ed

So i guess the best solution is to just hook that function and check if olmec is alive, if not, skip the cutscene and set the camera bounds manually

Mr-Auto commented 1 year ago

oh wait, that is just the spawn_effects virtual, it set's the camera stuff as it different for shortcut vs normal entrance

Dregu commented 1 year ago

Now I can disable olmec + cutscene, only disable the cutscene but have olmec or kill olmec whenever.

patch_olmec_kill_crash()
set_pre_tile_code_callback(function() return true end, "olmec")
state.level_gen.themes[THEME.OLMEC]:set_pre_spawn_effects(function()
  if #get_entities_by(ENT_TYPE.ACTIVEFLOOR_OLMEC, MASK.ACTIVEFLOOR, LAYER.BOTH) == 0 then
    state.level_gen.themes[THEME.DWELLING]:spawn_effects()
    return true
  end
end)
Mr-Auto commented 1 year ago

i may have even better solution, current problem: character can't move xd

Mr-Auto commented 1 year ago

skipping spawn_effects makes it so ENT_TYPE_FX_LEADER_FLAG is never spawn and "You feel forgiven." text is never shown (probably more)

Mr-Auto commented 1 year ago

you can test the new code, no need for theme hook but i can't figure out why i can't control the character

Mr-Auto commented 1 year ago

ok i figured out what it is, the player have the special behavior ic8 set that prevents him from doing anything

Mr-Auto commented 1 year ago

the movement is unlocked by the logic cutscene virtual 😭

Dregu commented 1 year ago

So ic8 is the cutscene behavior that's also making Ana walk in the intro etc, neat. That probably needs exposing and scripting capabilities.

Mr-Auto commented 1 year ago

So ic8 is the cutscene behavior that's also making Ana walk in the intro etc, neat. That probably needs exposing and scripting capabilities.

yeah, i think i commented that before. It's different from normal behavior, potentially even being a class based, so sometimes even having additional variables? thou this is just speculation over what I've seen in memory

anyway i may have a very hacky solution for this problem, will try it tomorrow

Dregu commented 1 year ago

I'm getting random crashes in olmec now, sometimes when just flying around, sometimes when loading the level. Also the camera bottom bound is still wrong when olmec doesn't spawn. (56.5 instead of 66.75)

patch_olmec_kill_crash()
set_pre_tile_code_callback(function() return true end, "olmec")
Mr-Auto commented 1 year ago

it's crashing in statemachine, but i think it might be related to the stack, looks like compiled overlunky code uses different convention. Will change the code to use using Detours tomorrow

Mr-Auto commented 1 year ago

The issue comes from state->unknown27 (the entity lookup), i need to reset it properly or something maybe?

Mr-Auto commented 1 year ago

This should be it for the olmec. Thou i didn't test a lot (like coop, online, entering level having HH etc.), but in theory those should not be affected

Mr-Auto commented 1 year ago

Ok, i reverse engineered almost the whole spawn_effects for olmec and tiamat. Stuff to note:

I will rewrite the olmec stuff a bit and make similar code for tiamat, there will be no need to loop thru entities or manually set the camera stuff

Mr-Auto commented 1 year ago

I'm 90% sure that all of this is safe, except for the first thing in olmec fix, i just don't know what the code is for. There is a lot of crap, plus jumps going all over the place

Mr-Auto commented 1 year ago

Hope we won't need to generate the entity types anymore, cause it will break this. Or maybe I add the CrushElevator later to the plugin, just so the type exists at least

Dregu commented 1 year ago

One issue with setting the elevator speed is that you can't set Hunduns speed to match, only y_limit there.

Mr-Auto commented 1 year ago

One issue with setting the elevator speed is that you can't set Hunduns speed to match, only y_limit there.

Now you can :) I also added the x increment, but not sure if it's of any use, game does just have it at 0 all the time

Dregu commented 1 year ago

I think you skipped something in the hundun rising update that updates the y_level to current bottom during the rising phase. This leads to weird hundun who constantly jumps down to the spawn level and then rises back up to jump down again, falls through the stopped elevator etc.

Mr-Auto commented 1 year ago

Wrong offset, at some point i switched the x/y around cuz they were the other way around, and rising the position uses a pointer to x/y, but forgot to change the code for the y_level update which only cares about the y speed