mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-23 01:59:43 +01: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:
parent
97deda2675
commit
593641ce82
1 changed files with 43 additions and 2 deletions
|
@ -2400,6 +2400,34 @@ void scriptclass::startgamemode(const enum StartMode mode)
|
||||||
VVV_exit(0);
|
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();
|
hardreset();
|
||||||
|
|
||||||
if (mode == Start_EDITOR)
|
if (mode == Start_EDITOR)
|
||||||
|
@ -2663,10 +2691,23 @@ void scriptclass::startgamemode(const enum StartMode mode)
|
||||||
obj.flags[73] = true;
|
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.resetplayer();
|
||||||
map.gotoroom(game.saverx, game.savery);
|
map.gotoroom(game.saverx, game.savery);
|
||||||
map.initmapdata();
|
map.initmapdata();
|
||||||
|
|
Loading…
Reference in a new issue