Make legacy checkpoints work along with respawn

This commit is contained in:
NepDisk 2024-07-30 04:25:41 -04:00
parent 2b7ebbe0a2
commit ec09f8a7e5
17 changed files with 266 additions and 27 deletions

View file

@ -281,6 +281,8 @@ typedef struct respawnvars_s
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 manual; // Respawn coords were manually set, please respawn exactly there
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
@ -549,6 +551,9 @@ typedef struct player_s
UINT8 laps; // Number of laps (optional)
UINT8 latestlap;
INT32 starpostnum; // The number of the last starpost you hit
tic_t starposttime; // NOIRE: The time of the last cheatcheck you hit
INT32 prevcheck; // Distance from Previous Legacy Checkpoint
INT32 nextcheck; // Distace to Next Legacy Checkpoint
UINT8 ctfteam; // 0 == Spectator, 1 == Red, 2 == Blue

View file

@ -1573,6 +1573,8 @@ void readlevelheader(MYFILE *f, INT32 num)
else
deh_warning("Level header %d: invalid unlockable number %d", num, i);
}
else if (fastcmp(word, "LEVELSELECT"))
mapheaderinfo[num-1]->levelselect = (UINT8)i;
else if (fastcmp(word, "SKYBOXSCALE"))
mapheaderinfo[num-1]->skybox_scalex = mapheaderinfo[num-1]->skybox_scaley = mapheaderinfo[num-1]->skybox_scalez = (INT16)i;
else if (fastcmp(word, "SKYBOXSCALEX"))
@ -1666,6 +1668,13 @@ void readlevelheader(MYFILE *f, INT32 num)
else
mapheaderinfo[num-1]->menuflags &= ~LF2_VISITNEEDED;
}
else if (fastcmp(word, "NOVISITNEEDED"))
{
if (i || word2[0] == 'T' || word2[0] == 'Y')
mapheaderinfo[num-1]->menuflags &= ~LF2_VISITNEEDED;
else
mapheaderinfo[num-1]->menuflags |= LF2_VISITNEEDED;
}
else if (fastcmp(word, "GRAVITY"))
mapheaderinfo[num-1]->gravity = FLOAT_TO_FIXED(atof(word2));
else

View file

@ -2080,6 +2080,10 @@ static inline void G_PlayerFinishLevel(INT32 player)
P_FlashPal(p, 0, 0); // Resets
p->starpostnum = 0;
p->starposttime = 0;
p->prevcheck = 0;
p->nextcheck = 0;
memset(&p->respawn, 0, sizeof (p->respawn));
// SRB2kart: Increment the "matches played" counter.
@ -2123,6 +2127,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
UINT8 ctfteam;
INT32 starpostnum;
tic_t starposttime; // The time of the last cheatcheck you hit
INT32 prevcheck; // Distance from Previous Legacy Checkpoint
INT32 nextcheck; // Distace to Next Legacy Checkpoint
INT32 exiting;
INT32 khudcardanimation;
INT16 totalring;
@ -2220,6 +2227,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
exiting = 0;
khudcardanimation = 0;
starpostnum = 0;
starposttime = 0;
prevcheck = 0;
nextcheck = 0;
xtralife = 0;
follower = NULL;
@ -2263,6 +2273,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
khudcardanimation = (exiting > 0) ? players[player].karthud[khud_cardanimation] : 0;
starpostnum = players[player].starpostnum;
starposttime = players[player].starposttime;
prevcheck = players[player].prevcheck;
prevcheck = players[player].nextcheck;
xtralife = players[player].xtralife;
@ -2308,6 +2321,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->followitem = followitem;
p->starpostnum = starpostnum;
p->starposttime = starposttime;
p->prevcheck = prevcheck;
p->nextcheck = nextcheck;
p->exiting = exiting;
p->karthud[khud_cardanimation] = khudcardanimation;

View file

@ -4401,10 +4401,21 @@ static void K_drawCheckpointDebugger(void)
if (stplyr != &players[displayplayers[0]]) // only for p1
return;
if (stplyr->starpostnum == numstarposts)
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Can finish)", stplyr->starpostnum, numstarposts));
if (numbosswaypoints > 0)
{
if (stplyr->starpostnum >= (numstarposts - (numstarposts/2)))
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Can finish)", stplyr->starpostnum, numstarposts));
else
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Skip: %d)", stplyr->starpostnum, numstarposts, ((numstarposts/2) + stplyr->starpostnum)));
V_DrawString(8, 192, 0, va("Waypoint dist: Prev %d, Next %d", stplyr->prevcheck, stplyr->nextcheck));
}
else
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d", stplyr->starpostnum, numstarposts));
{
if (stplyr->starpostnum == numstarposts)
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Can finish)", stplyr->starpostnum, numstarposts));
else
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d", stplyr->starpostnum, numstarposts));
}
}
static void K_DrawWaypointDebugger(void)

View file

@ -16,6 +16,7 @@
#include "g_game.h"
#include "m_random.h"
#include "p_local.h"
#include "p_mobj.h"
#include "p_slopes.h"
#include "p_setup.h"
#include "r_draw.h"
@ -7403,6 +7404,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->superring--;
}
// Start at lap 1 when using old checkpoint system just to be safe.
if ((numbosswaypoints > 0) && (player->laps == 0) && (numlaps > 0))
player->laps = 1;
if (player->stealingtimer == 0
&& player->rocketsneakertimer)
player->rocketsneakertimer--;
@ -8724,6 +8729,116 @@ void K_KartUpdatePosition(player_t *player)
player->position = position;
}
void K_KartLegacyUpdatePosition(player_t *player)
{
fixed_t position = 1;
fixed_t oldposition = player->position;
fixed_t i, ppcd, pncd, ipcd, incd;
fixed_t pmo, imo;
mobj_t *mo;
if (player->spectator || !player->mo)
return;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || !players[i].mo)
continue;
//if (G_RaceGametype())
{
if ((((players[i].starpostnum) + (numstarposts + 1) * players[i].laps) >
((player->starpostnum) + (numstarposts + 1) * player->laps)))
position++;
else if (((players[i].starpostnum) + (numstarposts+1)*players[i].laps) ==
((player->starpostnum) + (numstarposts+1)*player->laps))
{
ppcd = pncd = ipcd = incd = 0;
player->prevcheck = players[i].prevcheck = 0;
player->nextcheck = players[i].nextcheck = 0;
// This checks every thing on the map, and looks for MT_BOSS3WAYPOINT (the thing we're using for checkpoint wp's, for now)
for (mo = waypointcap; mo != NULL; mo = mo->tracer)
{
pmo = P_AproxDistance(P_AproxDistance( mo->x - player->mo->x,
mo->y - player->mo->y),
mo->z - player->mo->z) / FRACUNIT;
imo = P_AproxDistance(P_AproxDistance( mo->x - players[i].mo->x,
mo->y - players[i].mo->y),
mo->z - players[i].mo->z) / FRACUNIT;
if (mo->health == player->starpostnum && (!mo->movecount || mo->movecount == player->laps+1))
{
player->prevcheck += pmo;
ppcd++;
}
if (mo->health == (player->starpostnum + 1) && (!mo->movecount || mo->movecount == player->laps+1))
{
player->nextcheck += pmo;
pncd++;
}
if (mo->health == players[i].starpostnum && (!mo->movecount || mo->movecount == players[i].laps+1))
{
players[i].prevcheck += imo;
ipcd++;
}
if (mo->health == (players[i].starpostnum + 1) && (!mo->movecount || mo->movecount == players[i].laps+1))
{
players[i].nextcheck += imo;
incd++;
}
}
if (ppcd > 1) player->prevcheck /= ppcd;
if (pncd > 1) player->nextcheck /= pncd;
if (ipcd > 1) players[i].prevcheck /= ipcd;
if (incd > 1) players[i].nextcheck /= incd;
if ((players[i].nextcheck > 0 || player->nextcheck > 0) && !player->exiting)
{
if ((players[i].nextcheck - players[i].prevcheck) <
(player->nextcheck - player->prevcheck))
position++;
}
else if (!player->exiting)
{
if (players[i].prevcheck > player->prevcheck)
position++;
}
else
{
if (players[i].starposttime < player->starposttime)
position++;
}
}
}
/*else if (G_BattleGametype())
{
if (player->exiting) // Ends of match standings
{
if (players[i].marescore > player->marescore) // Only score matters
position++;
}
else
{
if (players[i].kartstuff[k_bumper] == player->kartstuff[k_bumper] && players[i].marescore > player->marescore)
position++;
else if (players[i].kartstuff[k_bumper] > player->kartstuff[k_bumper])
position++;
}
}*/
}
if (leveltime < starttime || oldposition == 0)
oldposition = position;
if (oldposition != position) // Changed places?
player->positiondelay = 10; // Position number growth
player->position = position;
}
//
// K_StripItems
//

View file

@ -98,6 +98,7 @@ INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage);
void K_SpawnDriftBoostExplosion(player_t *player, int stage);
void K_SpawnDriftElectricSparks(player_t *player);
void K_KartUpdatePosition(player_t *player);
void K_KartLegacyUpdatePosition(player_t *player);
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount);
void K_DropItems(player_t *player);
void K_DropRocketSneaker(player_t *player);

View file

@ -12,6 +12,7 @@
#include "k_respawn.h"
#include "doomdef.h"
#include "d_player.h"
#include "doomstat.h"
#include "k_kart.h"
#include "k_battle.h"
#include "g_game.h"
@ -128,7 +129,14 @@ void K_DoIngameRespawn(player_t *player)
P_ResetPlayer(player);
// Set up respawn position if invalid
if (player->respawn.wp != NULL && leveltime >= starttime)
if (player->respawn.manual == true)
{
player->respawn.distanceleft = 0;
player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip);
if (numbosswaypoints == 0)
player->respawn.manual = false; // one respawn only!
}
else if (player->respawn.wp != NULL && leveltime >= starttime)
{
const UINT32 dist = RESPAWN_DIST + (player->airtime * 48);
player->respawn.distanceleft = (dist * mapobjectscale) / FRACUNIT;
@ -386,6 +394,11 @@ static void K_MovePlayerToRespawnPoint(player_t *player)
else
{
// We can now drop!
if (gametyperules & GTR_CIRCUIT)
{
// 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;
}

View file

@ -17,6 +17,7 @@
#include "g_game.h"
#include "m_random.h"
#include "p_local.h"
#include "p_mobj.h"
#include "s_sound.h"
#include "r_main.h"
#include "st_stuff.h"
@ -593,13 +594,23 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
(void)snaptopost;
// Player must have touched all previous starposts
if (post->health - player->starpostnum > 1)
if ((post->health - player->starpostnum > 1) && (numbosswaypoints == 0))
{
if (!player->checkskip)
S_StartSound(toucher, sfx_lose);
player->checkskip = 3;
return;
}
// Going backwards triggers sound
if ((post->health >= ((numstarposts/2) + player->starpostnum)) && (numbosswaypoints > 0))
{
if (!player->checkskip)
S_StartSound(toucher, sfx_lose);
player->checkskip = 3;
return;
}
// With the parameter + angle setup, we can go up to 1365 star posts. Who needs that many?
if (post->health > 1365)
@ -610,6 +621,18 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
if (player->starpostnum >= post->health)
return; // Already hit this post
if (numbosswaypoints > 0) // Handles Respawning related things on Binary maps using legacy checkpoints
{
player->starposttime = player->realtime;
player->respawn.pointx = toucher->x;
player->respawn.pointy = toucher->y;
player->respawn.pointz = post->z;
player->respawn.pointangle = post->angle;
player->respawn.flip = ((post->flags2 & MF2_OBJECTFLIP) || (post->spawnpoint->options & MTF_OBJECTFLIP)) ? true : false; // store flipping
player->respawn.manual = true;
}
player->starpostnum = post->health;
}

View file

@ -10381,7 +10381,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
break;
case MT_BOSS3WAYPOINT:
// Remove before release
CONS_Alert(CONS_WARNING, "Boss waypoints are deprecated. Did you forget to remove the old checkpoints, too?\n");
//CONS_Alert(CONS_WARNING, "Boss waypoints are deprecated. Did you forget to remove the old checkpoints, too?\n");
break;
default:
break;
@ -12423,6 +12423,13 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
numstarposts++;
break;
}
case MT_BOSS3WAYPOINT:
mobj->health = mthing->angle;
mobj->movecount = mthing->extrainfo;
P_SetTarget(&mobj->tracer, waypointcap);
P_SetTarget(&waypointcap, mobj);
numbosswaypoints++;
break;
case MT_SPIKE:
// Pop up spikes!
if (mthing->options & MTF_OBJECTSPECIAL)

View file

@ -545,6 +545,7 @@ extern INT32 numhuntemeralds;
extern boolean runemeraldmanager;
extern UINT16 emeraldspawndelay;
extern INT32 numstarposts;
extern INT32 numbosswaypoints;
extern UINT16 bossdisabled;
extern boolean stoppedclock;
#endif

View file

@ -170,6 +170,9 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].laps);
WRITEUINT8(save_p, players[i].latestlap);
WRITEINT32(save_p, players[i].starpostnum);
WRITEUINT32(save_p, players[i].starposttime);
WRITEINT32(save_p, players[i].prevcheck);
WRITEINT32(save_p, players[i].nextcheck);
WRITEUINT8(save_p, players[i].ctfteam);
@ -377,7 +380,9 @@ static void P_NetArchivePlayers(void)
WRITEFIXED(save_p, players[i].respawn.pointx);
WRITEFIXED(save_p, players[i].respawn.pointy);
WRITEFIXED(save_p, players[i].respawn.pointz);
WRITEANGLE(save_p, players[i].respawn.pointangle);
WRITEUINT8(save_p, players[i].respawn.flip);
WRITEUINT8(save_p, players[i].respawn.manual);
WRITEUINT32(save_p, players[i].respawn.timer);
WRITEUINT32(save_p, players[i].respawn.airtimer);
WRITEUINT32(save_p, players[i].respawn.distanceleft);
@ -478,6 +483,9 @@ static void P_NetUnArchivePlayers(void)
players[i].laps = READUINT8(save_p); // Number of laps (optional)
players[i].latestlap = READUINT8(save_p);
players[i].starpostnum = READINT32(save_p);
players[i].starposttime = READUINT32(save_p);
players[i].prevcheck = READINT32(save_p);
players[i].nextcheck = READINT32(save_p);
players[i].ctfteam = READUINT8(save_p); // 1 == Red, 2 == Blue
@ -668,7 +676,9 @@ static void P_NetUnArchivePlayers(void)
players[i].respawn.pointx = READFIXED(save_p);
players[i].respawn.pointy = READFIXED(save_p);
players[i].respawn.pointz = READFIXED(save_p);
players[i].respawn.pointangle = READANGLE(save_p);
players[i].respawn.flip = (boolean)READUINT8(save_p);
players[i].respawn.manual = READUINT8(save_p);
players[i].respawn.timer = READUINT32(save_p);
players[i].respawn.airtimer = READUINT32(save_p);
players[i].respawn.distanceleft = READUINT32(save_p);

View file

@ -127,6 +127,7 @@ sector_t *spawnsectors;
line_t *spawnlines;
side_t *spawnsides;
INT32 numstarposts;
INT32 numbosswaypoints;
UINT16 bossdisabled;
boolean stoppedclock;
boolean levelloading;
@ -3715,6 +3716,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate)
circuitmap = false;
numstarposts = 0;
ssspheres = 0;
numbosswaypoints = 0;
if (!reloadinggamestate)
timeinmap = 0;
@ -4414,9 +4416,13 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Load the waypoints please!
if (gametyperules & GTR_CIRCUIT)
{
if (K_SetupWaypointList() == false)
if ((K_SetupWaypointList() == false) && (numbosswaypoints == 0))
{
CONS_Alert(CONS_ERROR, "Waypoints were not able to be setup! Player positions will not work correctly.\n");
CONS_Alert(CONS_ERROR, "Waypoints were not able to be setup and legacy checkpoints do not exist! Player positions will not work correctly.\n");
}
else if ((K_SetupWaypointList() == true) && numbosswaypoints > 0)
{
numbosswaypoints = 0;
}
}

View file

@ -909,11 +909,11 @@ boolean P_CanApplySlopePhysics(mobj_t *mo, pslope_t *slope)
return false;
}
if (slope->normal.x == 0 && slope->normal.y == 0)
/*if (slope->normal.x == 0 && slope->normal.y == 0)
{
// Flat slope? No such thing, man. No such thing.
return false;
}
}*/
if (mo->player != NULL)
{

View file

@ -1869,7 +1869,7 @@ static void K_HandleLapIncrement(player_t *player)
{
if (player)
{
if ((player->starpostnum == numstarposts) || (player->laps == 0))
if (((numbosswaypoints > 0) ? (player->starpostnum >= (numstarposts - (numstarposts/2))) : (player->starpostnum == numstarposts)) || (player->laps == 0))
{
size_t i = 0;
UINT8 nump = 0;
@ -4829,8 +4829,17 @@ DoneSection2:
player->speed = speed;
}
break;
case 10: // Unused
case 10: // Finish Line
{
if ((gametyperules & GTR_CIRCUIT) && (player->exiting == 0) && !(player->pflags & PF_HITFINISHLINE))
{
K_HandleLapIncrement(player);
//ACS_RunLapScript(mo, line);
//K_HandleLapIncrement(player);
player->pflags |= PF_HITFINISHLINE;
}
break;
}
case 11: // Unused
case 12: // Camera noclip
case 13: // Unused
@ -6018,7 +6027,7 @@ void P_SpawnSpecials(boolean fromnetsave)
{
case 10: // Circuit finish line (Unused)
// Remove before release
CONS_Alert(CONS_WARNING, "Finish line sector type is deprecated.\n");
//CONS_Alert(CONS_WARNING, "Finish line sector type is deprecated.\n");
break;
}
}

View file

@ -581,15 +581,28 @@ void P_Ticker(boolean run)
ps_playerthink_time = I_GetPreciseTime();
// First loop: Ensure all players' distance to the finish line are all accurate
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_UpdateDistanceFromFinishLine(&players[i]);
if (numbosswaypoints == 0)
{
// First loop: Ensure all players' distance to the finish line are all accurate
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_UpdateDistanceFromFinishLine(&players[i]);
// Second loop: Ensure all player positions reflect everyone's distances
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_KartUpdatePosition(&players[i]);
// Second loop: Ensure all player positions reflect everyone's distances
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_KartUpdatePosition(&players[i]);
}
else
{
// Use postion update code from v1
for (i = 0; i < MAXPLAYERS; i++)
{
K_KartLegacyUpdatePosition(&players[i]);
}
}
// OK! Now that we got all of that sorted, players can think!
for (i = 0; i < MAXPLAYERS; i++)

View file

@ -1989,7 +1989,7 @@ static void P_UpdatePlayerAngle(player_t *player)
max_left_turn = player->lturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS];
max_right_turn = player->rturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS];
CONS_Printf("----------------\nangle diff: %d - turning options: %d to %d - ", angle_diff, max_left_turn, max_right_turn);
//CONS_Printf("----------------\nangle diff: %d - turning options: %d to %d - ", angle_diff, max_left_turn, max_right_turn);
if (angle_diff > max_left_turn)
angle_diff = max_left_turn;
@ -2001,15 +2001,15 @@ static void P_UpdatePlayerAngle(player_t *player)
anglechange = cmd->angle<<TICCMD_REDUCE;
add_delta = false;
}
CONS_Printf("applied turn: %d\n", angle_diff);
//CONS_Printf("applied turn: %d\n", angle_diff);
if (add_delta) {
anglechange += angle_diff<<TICCMD_REDUCE;
anglechange &= ~0xFFFF; // Try to keep the turning somewhat similar to how it was before?
CONS_Printf("leftover turn (%s): %5d or %4d%%\n",
/*CONS_Printf("leftover turn (%s): %5d or %4d%%\n",
player_names[player-players],
(INT16) (cmd->angle - (player->mo->angle>>TICCMD_REDUCE)),
(INT16) (cmd->angle - (player->mo->angle>>TICCMD_REDUCE)) * 100 / (angle_diff ? angle_diff : 1));
(INT16) (cmd->angle - (player->mo->angle>>TICCMD_REDUCE)) * 100 / (angle_diff ? angle_diff : 1));*/
}

View file

@ -782,7 +782,7 @@ void ST_drawTitleCard(void)
if (!LUA_HudEnabled(hud_stagetitle))
goto luahook;
if (timeinmap > 113)
if (timeinmap > 113 || timeinmap < 6)
goto luahook;
lvlw = V_LevelNameWidth(lvlttl);