Checkpoints: add respawning behavior for players

- Add checkpointId to player_t and netsave
- checkpointId persists if the map is reloaded, but not if
  the map is changed or if "resetplayers" is ticked
- Players spawn at the last touched checkpoint instead of
  at a player start
- Tether sparkles fly out of the player in a circle
This commit is contained in:
James R 2023-08-30 21:25:58 -07:00 committed by toaster
parent e83923a365
commit 2bbf69ded3
3 changed files with 41 additions and 8 deletions

View file

@ -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

View file

@ -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

View file

@ -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