diff --git a/src/d_player.h b/src/d_player.h index cc176671c..be4de8b48 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -337,6 +337,7 @@ struct respawnvars_t fixed_t pointx; // Respawn position coords to go towards fixed_t pointy; fixed_t pointz; + angle_t pointangle; // Only used when wp is NULL boolean flip; // Flip upside down or not tic_t timer; // Time left on respawn animation once you're there tic_t airtimer; // Time spent in the air before respawning diff --git a/src/g_game.c b/src/g_game.c index 55f1ce2ac..203908c92 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2497,8 +2497,7 @@ void G_MovePlayerToSpawnOrCheatcheck(INT32 playernum) rsp->pointx = pos.x; rsp->pointy = pos.y; rsp->pointz = pos.z; - - players[playernum].mo->angle = Obj_GetCheckpointRespawnAngle(checkpoint); + rsp->pointangle = Obj_GetCheckpointRespawnAngle(checkpoint); Obj_ActivateCheckpointInstantly(checkpoint); diff --git a/src/k_respawn.c b/src/k_respawn.c index 21af8253d..7c650ff63 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -14,6 +14,7 @@ #include "d_player.h" #include "k_kart.h" #include "k_battle.h" +#include "k_objects.h" // Obj_FindCheckpoint, etc #include "g_game.h" #include "p_local.h" #include "p_tick.h" @@ -161,6 +162,9 @@ void K_DoIngameRespawn(player_t *player) K_TumbleInterrupt(player); P_ResetPlayer(player); + mobj_t *checkpoint; + vector3_t pos; + // Set up respawn position if invalid if (player->respawn.manual == true) { @@ -192,6 +196,21 @@ void K_DoIngameRespawn(player_t *player) K_RespawnAtWaypoint(player, player->respawn.wp); } } + else if ((gametyperules & GTR_CHECKPOINTS) + && player->checkpointId + && (checkpoint = Obj_FindCheckpoint(player->checkpointId)) + && Obj_GetCheckpointRespawnPosition(checkpoint, &pos)) + { + player->respawn.wp = NULL; + player->respawn.flip = (checkpoint->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean! + player->respawn.pointx = pos.x; + player->respawn.pointy = pos.y; + player->respawn.pointz = pos.z + K_RespawnOffset(player, player->respawn.flip); + + player->respawn.pointangle = Obj_GetCheckpointRespawnAngle(checkpoint); + + player->respawn.distanceleft = 0; + } else { UINT32 bestdist = UINT32_MAX; @@ -242,6 +261,7 @@ void K_DoIngameRespawn(player_t *player) player->respawn.pointx = 0; player->respawn.pointy = 0; player->respawn.pointz = 0; + player->respawn.pointangle = 0; player->respawn.flip = false; } else @@ -252,7 +272,7 @@ void K_DoIngameRespawn(player_t *player) player->respawn.pointx = beststart->x << FRACBITS; player->respawn.pointy = beststart->y << FRACBITS; - player->mo->angle = ( beststart->angle * ANG1 ); + player->respawn.pointangle = ( beststart->angle * ANG1 ); s = R_PointInSubsector(beststart->x << FRACBITS, beststart->y << FRACBITS)->sector; @@ -474,6 +494,11 @@ static void K_MovePlayerToRespawnPoint(player_t *player) else { // We can now drop! + if (gametyperules & GTR_CHECKPOINTS) + { + // Of course, in gametypes where there's a clear and intended progression, set our direction. + P_SetPlayerAngle(player, (player->drawangle = player->respawn.pointangle)); + } player->respawn.state = RESPAWNST_DROP; return; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 16226b024..35ee86ade 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12560,7 +12560,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) else if (mobj->z == mobj->floorz) mobj->eflags |= MFE_ONGROUND; - mobj->angle = angle; + mobj->angle = p->drawangle = angle; // FAULT if (gamestate == GS_LEVEL && leveltime > introtime && !p->spectator) @@ -12575,6 +12575,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) p->respawn.pointx = x; p->respawn.pointy = y; p->respawn.pointz = z; + p->respawn.pointangle = angle; } P_AfterPlayerSpawn(playernum); @@ -12629,7 +12630,7 @@ void P_MovePlayerToCheatcheck(INT32 playernum) } } else - p->drawangle = mobj->angle; // default to the camera angle + p->drawangle = mobj->angle = p->respawn.pointangle; K_DoIngameRespawn(p); p->respawn.truedeath = true;