diff --git a/src/d_player.h b/src/d_player.h index 5e57cfc92..6a3598def 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -742,6 +742,7 @@ struct player_t UINT8 latestlap; UINT32 lapPoints; // Points given from laps INT32 cheatchecknum; // The number of the last cheatcheck you hit + INT32 checkpointId; // Players respawn here, objects/checkpoint.cpp UINT8 ctfteam; // 0 == Spectator, 1 == Red, 2 == Blue diff --git a/src/g_game.c b/src/g_game.c index ac05c0b6f..56ad5149b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -71,6 +71,7 @@ #include "k_zvote.h" #include "music.h" #include "k_roulette.h" +#include "k_objects.h" #ifdef HAVE_DISCORDRPC #include "discord.h" @@ -2044,6 +2045,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT16 nocontrol; INT32 khudfault; INT32 kickstartaccel; + INT32 checkpointId; boolean enteredGame; roundconditions_t roundconditions; @@ -2249,6 +2251,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) skyboxviewpoint = skyboxcenterpoint = NULL; } + checkpointId = players[player].checkpointId; + enteredGame = players[player].enteredGame; p = &players[player]; @@ -2305,6 +2309,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->karthud[khud_fault] = khudfault; p->nocontrol = nocontrol; p->kickstartaccel = kickstartaccel; + p->checkpointId = checkpointId; p->ringvolume = 255; @@ -2453,19 +2458,39 @@ void G_SpawnPlayer(INT32 playernum) void G_MovePlayerToSpawnOrCheatcheck(INT32 playernum) { -#if 0 - if (leveltime <= introtime && !players[playernum].spectator) - P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); - else - P_MovePlayerToCheatcheck(playernum); -#else // Player's first spawn should be at the "map start". // I.e. level load or join mid game. if (leveltime > starttime && players[playernum].jointime > 1 && K_PodiumSequence() == false) + { P_MovePlayerToCheatcheck(playernum); + } else - P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); -#endif + { + mobj_t *checkpoint; + vector3_t pos; + + if (players[playernum].checkpointId && + (checkpoint = Obj_FindCheckpoint(players[playernum].checkpointId)) && + Obj_GetCheckpointRespawnPosition(checkpoint, &pos)) + { + respawnvars_t *rsp = &players[playernum].respawn; + + rsp->wp = NULL; + rsp->pointx = pos.x; + rsp->pointy = pos.y; + rsp->pointz = pos.z; + + players[playernum].mo->angle = Obj_GetCheckpointRespawnAngle(checkpoint); + + Obj_ActivateCheckpointInstantly(checkpoint); + + P_MovePlayerToCheatcheck(playernum); + } + else + { + P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); + } + } } mapthing_t *G_FindTeamStart(INT32 playernum) @@ -5669,6 +5694,11 @@ void G_InitNew(UINT8 pencoremode, INT32 map, boolean resetplayer, boolean skippr players[i].totalring = 0; players[i].score = 0; } + + if (resetplayer || map != gamemap) + { + players[i].checkpointId = 0; + } } // clear itemfinder, just in case diff --git a/src/p_saveg.c b/src/p_saveg.c index 48bbc31ed..c3db3804c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -267,6 +267,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].latestlap); WRITEUINT32(save->p, players[i].lapPoints); WRITEINT32(save->p, players[i].cheatchecknum); + WRITEINT32(save->p, players[i].checkpointId); WRITEUINT8(save->p, players[i].ctfteam); @@ -777,6 +778,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].latestlap = READUINT8(save->p); players[i].lapPoints = READUINT32(save->p); players[i].cheatchecknum = READINT32(save->p); + players[i].checkpointId = READINT32(save->p); players[i].ctfteam = READUINT8(save->p); // 1 == Red, 2 == Blue