1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-25 22:18:30 +02:00

Always destroy and create new player in startgamemode

This fixes a bug where players could flip in mid-air at the start of
custom levels whose start points were in mid-air, because
onground/onroof were not being reset. This could also be done when
loading in to a save with a checkpoint in mid-air. All that's required
is to exit the game while standing on a surface (or otherwise having a
nonzero onground/onroof).

This reminded me that there were other variables on the player entity
persisting through that made loading in to a level not have a totally
clean slate, such as walkingframe (which could affect sequencing
individual TASes together into one TAS), so it's better to just destroy
the player entity and recreate it.

Except some attributes still have to be persisted for 2.2 and 2.0
glitchrunner mode. But it's better that this is done via a whitelist
rather than a blacklist.

The player duplicate removal code in hardreset is mostly redundant now
(except for some very unlikely corner cases), but there's nothing wrong
with having redundant code as long as it's not harmful. I had a
paragraph here justifying why it could be removed but decided it was
simpler to just keep it.
This commit is contained in:
Misa 2022-12-29 15:00:01 -08:00
parent 97deda2675
commit 593641ce82

View File

@ -2400,6 +2400,34 @@ void scriptclass::startgamemode(const enum StartMode mode)
VVV_exit(0);
}
struct
{
bool initialized;
int size;
int cx;
int cy;
int w;
int h;
}
player_hitbox;
SDL_zero(player_hitbox);
if (GlitchrunnerMode_less_than_or_equal(Glitchrunner2_2))
{
/* Preserve player hitbox */
const int player_idx = obj.getplayer();
if (INBOUNDS_VEC(player_idx, obj.entities))
{
const entclass* player = &obj.entities[player_idx];
player_hitbox.initialized = true;
player_hitbox.size = player->size;
player_hitbox.cx = player->cx;
player_hitbox.cy = player->cy;
player_hitbox.w = player->w;
player_hitbox.h = player->h;
}
}
hardreset();
if (mode == Start_EDITOR)
@ -2663,10 +2691,23 @@ void scriptclass::startgamemode(const enum StartMode mode)
obj.flags[73] = true;
}
if (obj.entities.empty())
obj.entities.clear();
obj.createentity(game.savex, game.savey, 0, 0);
if (player_hitbox.initialized)
{
obj.createentity(game.savex, game.savey, 0, 0); //In this game, constant, never destroyed
/* Restore player hitbox */
const int player_idx = obj.getplayer();
if (INBOUNDS_VEC(player_idx, obj.entities))
{
entclass* player = &obj.entities[player_idx];
player->size = player_hitbox.size;
player->cx = player_hitbox.cx;
player->cy = player_hitbox.cy;
player->w = player_hitbox.w;
player->h = player_hitbox.h;
}
}
map.resetplayer();
map.gotoroom(game.saverx, game.savery);
map.initmapdata();