mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge remote-tracking branch 'remotes/origin/master' into reasonable-drawdist
This commit is contained in:
commit
e1998e731e
23 changed files with 267 additions and 89 deletions
|
|
@ -4043,10 +4043,27 @@ static void HandleConnect(SINT8 node)
|
|||
UINT8 maxplayers = min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxconnections.value);
|
||||
UINT8 connectedplayers = 0;
|
||||
|
||||
|
||||
for (i = dedicated ? 1 : 0; i < MAXPLAYERS; i++)
|
||||
if (playernode[i] != UINT8_MAX) // We use this to count players because it is affected by SV_AddWaitingPlayers when more than one client joins on the same tic, unlike playeringame and D_NumPlayers. UINT8_MAX denotes no node for that player
|
||||
{
|
||||
// We use this to count players because it is affected by SV_AddWaitingPlayers when
|
||||
// more than one client joins on the same tic, unlike playeringame and D_NumPlayers.
|
||||
// UINT8_MAX denotes no node for that player.
|
||||
|
||||
if (playernode[i] != UINT8_MAX)
|
||||
{
|
||||
// Sal: This hack sucks, but it should be safe.
|
||||
// playeringame is set for bots immediately; they are deterministic instead of a netxcmd.
|
||||
// If a bot is added with netxcmd in the future, then the node check is still here too.
|
||||
// So at worst, a theoretical netxcmd added bot will block real joiners for the time
|
||||
// it takes for the command to process, but not cause any horrifying player overwriting.
|
||||
if (playeringame[i] && players[i].bot)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
connectedplayers++;
|
||||
}
|
||||
}
|
||||
|
||||
banrecord_t *ban = SV_GetBanByAddress(node);
|
||||
if (ban == NULL)
|
||||
|
|
|
|||
|
|
@ -7282,13 +7282,6 @@ void KartEncore_OnChange(void)
|
|||
void KartEliminateLast_OnChange(void);
|
||||
void KartEliminateLast_OnChange(void)
|
||||
{
|
||||
#ifndef DEVELOP
|
||||
if (K_CanChangeRules(false) == false)
|
||||
{
|
||||
CV_StealthSet(&cv_karteliminatelast, cv_karteliminatelast.defaultvalue);
|
||||
}
|
||||
#endif
|
||||
|
||||
P_CheckRacers();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -578,6 +578,15 @@ struct altview_t
|
|||
INT32 tics;
|
||||
};
|
||||
|
||||
// enum for saved lap times
|
||||
typedef enum
|
||||
{
|
||||
LAP_CUR,
|
||||
LAP_BEST,
|
||||
LAP_LAST,
|
||||
LAP__MAX
|
||||
} laptime_e;
|
||||
|
||||
extern altview_t titlemapcam;
|
||||
|
||||
// ========================================================================
|
||||
|
|
@ -897,6 +906,7 @@ struct player_t
|
|||
|
||||
INT16 totalring; // Total number of rings obtained for GP
|
||||
tic_t realtime; // integer replacement for leveltime
|
||||
tic_t laptime[LAP__MAX];
|
||||
UINT8 laps; // Number of laps (optional)
|
||||
UINT8 latestlap;
|
||||
UINT32 lapPoints; // Points given from laps
|
||||
|
|
|
|||
|
|
@ -871,7 +871,6 @@ extern boolean inDuel;
|
|||
extern tic_t bombflashtimer; // Used to avoid causing seizures if multiple mines explode close to you :)
|
||||
extern boolean legitimateexit;
|
||||
extern boolean comebackshowninfo;
|
||||
extern tic_t curlap, bestlap;
|
||||
|
||||
#define VOTE_SPECIAL (MAXPLAYERS)
|
||||
#define VOTE_TOTAL (MAXPLAYERS+1)
|
||||
|
|
|
|||
51
src/g_game.c
51
src/g_game.c
|
|
@ -147,6 +147,7 @@ boolean modifiedgame = false; // Set if homebrew PWAD stuff has been added.
|
|||
boolean majormods = false; // Set if Lua/Gameplay SOC/replacement map has been added.
|
||||
boolean savemoddata = false;
|
||||
boolean usedCheats = false; // Set when a "cheats on" is ever used.
|
||||
boolean usedTourney = false; // Entered the "Tournament Mode" cheat.
|
||||
UINT8 paused;
|
||||
UINT8 modeattacking = ATTACKING_NONE;
|
||||
boolean imcontinuing = false;
|
||||
|
|
@ -322,8 +323,6 @@ boolean inDuel; // Boolean, keeps track of if it is a 1v1
|
|||
tic_t bombflashtimer = 0; // Cooldown before another FlashPal can be intialized by a bomb exploding near a displayplayer. Avoids seizures.
|
||||
boolean legitimateexit; // Did this client actually finish the match?
|
||||
boolean comebackshowninfo; // Have you already seen the "ATTACK OR PROTECT" message?
|
||||
tic_t curlap; // Current lap time
|
||||
tic_t bestlap; // Best lap time
|
||||
|
||||
boolean precache = true; // if true, load all graphics at start
|
||||
|
||||
|
|
@ -344,14 +343,10 @@ void G_ClearRecords(void)
|
|||
{
|
||||
UINT16 i;
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
{
|
||||
memset(&skins[i].records, 0, sizeof(skins[i].records));
|
||||
}
|
||||
|
||||
for (i = 0; i < nummapheaders; i++)
|
||||
{
|
||||
memset(&mapheaderinfo[i]->records, 0, sizeof(recorddata_t));
|
||||
memset(&mapheaderinfo[i]->records.timeattack, 0, sizeof(recordtimes_t));
|
||||
memset(&mapheaderinfo[i]->records.spbattack, 0, sizeof(recordtimes_t));
|
||||
}
|
||||
|
||||
cupheader_t *cup;
|
||||
|
|
@ -360,14 +355,11 @@ void G_ClearRecords(void)
|
|||
memset(&cup->windata, 0, sizeof(cup->windata));
|
||||
}
|
||||
|
||||
unloaded_skin_t *unloadedskin, *nextunloadedskin = NULL;
|
||||
for (unloadedskin = unloadedskins; unloadedskin; unloadedskin = nextunloadedskin)
|
||||
{
|
||||
nextunloadedskin = unloadedskin->next;
|
||||
Z_Free(unloadedskin);
|
||||
}
|
||||
unloadedskins = NULL;
|
||||
|
||||
// TODO: Technically, these should only remove time attack records here.
|
||||
// But I'm out of juice for dev (+ literally, just finished some OJ).
|
||||
// The stats need to be cleared in M_ClearStats, and I guess there's
|
||||
// no perfect place to wipe mapvisited because it's not actually part of
|
||||
// basegame progression... so here's fine for launch. ~toast 100424
|
||||
unloaded_mapheader_t *unloadedmap, *nextunloadedmap = NULL;
|
||||
for (unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = nextunloadedmap)
|
||||
{
|
||||
|
|
@ -561,8 +553,8 @@ void G_UpdateRecords(void)
|
|||
|
||||
if (modeattacking & ATTACKING_LAP)
|
||||
{
|
||||
if ((record->lap == 0) || (bestlap < record->lap))
|
||||
record->lap = bestlap;
|
||||
if ((record->lap == 0) || (players[consoleplayer].laptime[LAP_BEST] < record->lap))
|
||||
record->lap = players[consoleplayer].laptime[LAP_BEST];
|
||||
}
|
||||
|
||||
// Check emblems when level data is updated
|
||||
|
|
@ -606,7 +598,7 @@ static void G_UpdateRecordReplays(void)
|
|||
// Save demo!
|
||||
bestdemo[255] = '\0';
|
||||
lastdemo[255] = '\0';
|
||||
G_SetDemoTime(players[consoleplayer].realtime, bestlap);
|
||||
G_SetDemoTime(players[consoleplayer].realtime, players[consoleplayer].laptime[LAP_BEST]);
|
||||
G_CheckDemoStatus();
|
||||
|
||||
gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s",
|
||||
|
|
@ -2179,6 +2171,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
level_tally_t tally;
|
||||
boolean tallyactive;
|
||||
|
||||
tic_t laptime[LAP__MAX];
|
||||
|
||||
INT32 i;
|
||||
|
||||
// This needs to be first, to permit it to wipe extra information
|
||||
jointime = players[player].jointime;
|
||||
if (jointime <= 1)
|
||||
|
|
@ -2206,6 +2202,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
kartspeed = skins[players[player].skin].kartspeed;
|
||||
kartweight = skins[players[player].skin].kartweight;
|
||||
charflags = skins[players[player].skin].flags;
|
||||
|
||||
for (i = 0; i < LAP__MAX; i++)
|
||||
{
|
||||
laptime[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2218,6 +2219,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
kartweight = players[player].kartweight;
|
||||
|
||||
charflags = (skinflags & SF_IRONMAN) ? skinflags : players[player].charflags;
|
||||
|
||||
for (i = 0; i < LAP__MAX; i++)
|
||||
{
|
||||
laptime[i] = players[player].laptime[i];
|
||||
}
|
||||
}
|
||||
lastfakeskin = players[player].lastfakeskin;
|
||||
|
||||
|
|
@ -2456,6 +2462,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->lapPoints = lapPoints;
|
||||
p->totalring = totalring;
|
||||
|
||||
for (i = 0; i < LAP__MAX; i++)
|
||||
{
|
||||
p->laptime[i] = laptime[i];
|
||||
}
|
||||
|
||||
p->bot = bot;
|
||||
p->botvars.difficulty = botdifficulty;
|
||||
p->rings = rings;
|
||||
|
|
@ -2519,8 +2530,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
// Check to make sure their color didn't change somehow...
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (p->ctfteam == 1 && p->skincolor != skincolor_redteam)
|
||||
{
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di
|
|||
extern INT32 pausedelay;
|
||||
extern boolean pausebreakkey;
|
||||
|
||||
extern boolean usedTourney;
|
||||
|
||||
extern boolean promptactive;
|
||||
|
||||
extern consvar_t cv_tutorialprompt;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ INT32 K_StartingBumperCount(void)
|
|||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
return 0;
|
||||
|
||||
if (battleprisons || K_CheckBossIntro())
|
||||
if (battleprisons || K_CheckBossIntro() || !K_CanChangeRules(true))
|
||||
{
|
||||
if (grandprixinfo.gp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1889,7 +1889,7 @@ tic_t K_TranslateTimer(tic_t drawtime, UINT8 mode, INT32 *return_jitter)
|
|||
{
|
||||
INT32 jitter = 0;
|
||||
|
||||
if (!mode)
|
||||
if (!mode && drawtime != UINT32_MAX)
|
||||
{
|
||||
if (timelimitintics > 0)
|
||||
{
|
||||
|
|
@ -1948,7 +1948,6 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U
|
|||
// TIME_X = BASEVIDWIDTH-124; // 196
|
||||
// TIME_Y = 6; // 6
|
||||
|
||||
tic_t worktime;
|
||||
INT32 jitter = 0;
|
||||
|
||||
drawtime = K_TranslateTimer(drawtime, mode, &jitter);
|
||||
|
|
@ -1957,19 +1956,27 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U
|
|||
|
||||
TX += 33;
|
||||
|
||||
worktime = drawtime/(60*TICRATE);
|
||||
|
||||
if (worktime >= 100)
|
||||
if (drawtime == UINT32_MAX)
|
||||
;
|
||||
else if (mode && !drawtime)
|
||||
{
|
||||
jitter = (drawtime & 1 ? 1 : -1);
|
||||
worktime = 99;
|
||||
drawtime = (100*(60*TICRATE))-1;
|
||||
}
|
||||
// apostrophe location _'__ __
|
||||
V_DrawTimerString(TX+24, TY+3, splitflags, va("'"));
|
||||
|
||||
if (mode && !drawtime)
|
||||
V_DrawTimerString(TX, TY+3, splitflags, "--'--\"--");
|
||||
// quotation mark location _ __"__
|
||||
V_DrawTimerString(TX+60, TY+3, splitflags, va("\""));
|
||||
}
|
||||
else
|
||||
{
|
||||
tic_t worktime = drawtime/(60*TICRATE);
|
||||
|
||||
if (worktime >= 100)
|
||||
{
|
||||
jitter = (drawtime & 1 ? 1 : -1);
|
||||
worktime = 99;
|
||||
drawtime = (100*(60*TICRATE))-1;
|
||||
}
|
||||
|
||||
// minutes time 00 __ __
|
||||
V_DrawTimerString(TX, TY+3+jitter, splitflags, va("%d", worktime/10));
|
||||
V_DrawTimerString(TX+12, TY+3-jitter, splitflags, va("%d", worktime%10));
|
||||
|
|
@ -6089,7 +6096,26 @@ void K_drawKartHUD(void)
|
|||
{
|
||||
bool ta = modeattacking && !demo.playback;
|
||||
INT32 flags = V_HUDTRANS|V_SLIDEIN|V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y + (ta ? 2 : 0), flags, 0);
|
||||
|
||||
tic_t realtime = stplyr->realtime;
|
||||
|
||||
if (stplyr->karthud[khud_lapanimation]
|
||||
&& !stplyr->exiting
|
||||
&& stplyr->laptime[LAP_LAST] != 0
|
||||
&& stplyr->laptime[LAP_LAST] != UINT32_MAX)
|
||||
{
|
||||
if ((stplyr->karthud[khud_lapanimation] / 5) & 1)
|
||||
{
|
||||
realtime = stplyr->laptime[LAP_LAST];
|
||||
}
|
||||
else
|
||||
{
|
||||
realtime = UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
K_drawKartTimestamp(realtime, TIME_X, TIME_Y + (ta ? 2 : 0), flags, 0);
|
||||
|
||||
if (modeattacking)
|
||||
{
|
||||
if (ta)
|
||||
|
|
|
|||
70
src/k_kart.c
70
src/k_kart.c
|
|
@ -72,6 +72,16 @@
|
|||
// comeback is Battle Mode's karma comeback, also bool
|
||||
// mapreset is set when enough players fill an empty server
|
||||
|
||||
boolean K_ThunderDome(void)
|
||||
{
|
||||
if (K_CanChangeRules(true))
|
||||
{
|
||||
return (boolean)cv_thunderdome.value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// lat: used for when the player is in some weird state where it wouldn't be wise for it to be overwritten by another object that does similarly wacky shit.
|
||||
boolean K_isPlayerInSpecialState(player_t *p)
|
||||
{
|
||||
|
|
@ -12181,7 +12191,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
if (player->ringboxdelay == 0)
|
||||
{
|
||||
UINT32 award = 5*player->ringboxaward + 10;
|
||||
if (!cv_thunderdome.value)
|
||||
if (!K_ThunderDome())
|
||||
award = 3 * award / 2;
|
||||
|
||||
if (modeattacking & ATTACKING_SPB)
|
||||
|
|
@ -13559,6 +13569,7 @@ void K_CheckSpectateStatus(boolean considermapreset)
|
|||
{
|
||||
UINT8 respawnlist[MAXPLAYERS];
|
||||
UINT8 i, j, numingame = 0, numjoiners = 0;
|
||||
UINT8 numhumans = 0, numbots = 0;
|
||||
|
||||
// Maintain spectate wait timer
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -13571,6 +13582,16 @@ void K_CheckSpectateStatus(boolean considermapreset)
|
|||
if (!players[i].spectator)
|
||||
{
|
||||
numingame++;
|
||||
|
||||
if (players[i].bot)
|
||||
{
|
||||
numbots++;
|
||||
}
|
||||
else
|
||||
{
|
||||
numhumans++;
|
||||
}
|
||||
|
||||
players[i].spectatewait = 0;
|
||||
players[i].spectatorReentry = 0;
|
||||
continue;
|
||||
|
|
@ -13600,7 +13621,7 @@ void K_CheckSpectateStatus(boolean considermapreset)
|
|||
return;
|
||||
|
||||
// DON'T allow if you've hit the in-game player cap
|
||||
if (cv_maxplayers.value && numingame >= cv_maxplayers.value)
|
||||
if (cv_maxplayers.value && numhumans >= cv_maxplayers.value)
|
||||
return;
|
||||
|
||||
// Get the number of players in game, and the players to be de-spectated.
|
||||
|
|
@ -13684,16 +13705,47 @@ void K_CheckSpectateStatus(boolean considermapreset)
|
|||
}
|
||||
}
|
||||
|
||||
const UINT8 previngame = numingame;
|
||||
INT16 removeBotID = MAXPLAYERS - 1;
|
||||
|
||||
// Finally, we can de-spectate everyone!
|
||||
for (i = 0; i < numjoiners; i++)
|
||||
{
|
||||
//CONS_Printf("player %s is joining on tic %d\n", player_names[respawnlist[i]], leveltime);
|
||||
|
||||
P_SpectatorJoinGame(&players[respawnlist[i]]);
|
||||
|
||||
// Hit the in-game player cap while adding people?
|
||||
if (cv_maxplayers.value && numingame+i >= cv_maxplayers.value)
|
||||
break;
|
||||
if (cv_maxplayers.value && numingame >= cv_maxplayers.value)
|
||||
{
|
||||
if (numbots > 0)
|
||||
{
|
||||
// Find a bot to kill to make room
|
||||
while (removeBotID >= 0)
|
||||
{
|
||||
if (playeringame[removeBotID] && players[removeBotID].bot)
|
||||
{
|
||||
//CONS_Printf("bot %s kicked to make room on tic %d\n", player_names[removeBotID], leveltime);
|
||||
CL_RemovePlayer(removeBotID, KR_LEAVE);
|
||||
numbots--;
|
||||
numingame--;
|
||||
break;
|
||||
}
|
||||
|
||||
removeBotID--;
|
||||
}
|
||||
|
||||
if (removeBotID < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//CONS_Printf("player %s is joining on tic %d\n", player_names[respawnlist[i]], leveltime);
|
||||
P_SpectatorJoinGame(&players[respawnlist[i]]);
|
||||
numhumans++;
|
||||
numingame++;
|
||||
}
|
||||
|
||||
if (considermapreset == false)
|
||||
|
|
@ -13702,7 +13754,7 @@ void K_CheckSpectateStatus(boolean considermapreset)
|
|||
// Reset the match when 2P joins 1P, DUEL mode
|
||||
// Reset the match when 3P joins 1P and 2P, DUEL mode must be disabled
|
||||
extern consvar_t cv_debugnewchallenger;
|
||||
if (i > 0 && !mapreset && gamestate == GS_LEVEL && (numingame < 3 && numingame+i >= 2) && !cv_debugnewchallenger.value)
|
||||
if (i > 0 && !mapreset && gamestate == GS_LEVEL && (previngame < 3 && numingame >= 2) && !cv_debugnewchallenger.value)
|
||||
{
|
||||
Music_Play("comeon"); // COME ON
|
||||
mapreset = 3*TICRATE; // Even though only the server uses this for game logic, set for everyone for HUD
|
||||
|
|
|
|||
|
|
@ -274,6 +274,8 @@ void K_MakeObjectReappear(mobj_t *mo);
|
|||
|
||||
void K_BumperInflate(player_t *player);
|
||||
|
||||
boolean K_ThunderDome(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -478,7 +478,6 @@ typedef enum
|
|||
{
|
||||
gopt_spacer0 = 0,
|
||||
gopt_gamespeed,
|
||||
gopt_baselapcount,
|
||||
gopt_frantic,
|
||||
gopt_encore,
|
||||
gopt_exitcountdown,
|
||||
|
|
|
|||
|
|
@ -640,12 +640,15 @@ void podiumData_s::Draw(void)
|
|||
|
||||
if (emeraldNum == 0)
|
||||
{
|
||||
emeraldPatch = static_cast<patch_t*>( W_CachePatchName("K_BLNA", PU_CACHE) );
|
||||
// Prize -- todo, currently using fake Emerald
|
||||
emeraldColor = SKINCOLOR_GOLD;
|
||||
}
|
||||
else
|
||||
{
|
||||
emeraldColor = static_cast<skincolornum_t>( SKINCOLOR_CHAOSEMERALD1 + ((emeraldNum - 1) % 7) );
|
||||
}
|
||||
|
||||
{
|
||||
std::string emeraldName;
|
||||
if (emeraldNum > 7)
|
||||
{
|
||||
|
|
@ -853,12 +856,15 @@ void podiumData_s::Draw(void)
|
|||
|
||||
if (emeraldNum == 0)
|
||||
{
|
||||
emeraldOverlay = static_cast<patch_t*>( W_CachePatchName("KBLNC0", PU_CACHE) );
|
||||
// Prize -- todo, currently using fake Emerald
|
||||
emeraldColor = SKINCOLOR_GOLD;
|
||||
}
|
||||
else
|
||||
{
|
||||
emeraldColor = static_cast<skincolornum_t>( SKINCOLOR_CHAOSEMERALD1 + ((emeraldNum - 1) % 7) );
|
||||
}
|
||||
|
||||
{
|
||||
if (emeraldNum > 7)
|
||||
{
|
||||
emeraldOverlay = static_cast<patch_t*>( W_CachePatchName("SEMRA0", PU_CACHE) );
|
||||
|
|
|
|||
58
src/m_cond.c
58
src/m_cond.c
|
|
@ -650,7 +650,8 @@ void M_ClearConditionSet(UINT16 set)
|
|||
// Clear ALL secrets.
|
||||
void M_ClearStats(void)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT16 i;
|
||||
|
||||
gamedata->totalplaytime = 0;
|
||||
gamedata->totalnetgametime = 0;
|
||||
gamedata->timeattackingtotaltime = 0;
|
||||
|
|
@ -678,6 +679,54 @@ void M_ClearStats(void)
|
|||
gamedata->musicstate = GDMUSIC_NONE;
|
||||
|
||||
gamedata->importprofilewins = false;
|
||||
|
||||
// Skins only store stats, not progression metrics. Good to clear entirely here.
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
{
|
||||
memset(&skins[i].records, 0, sizeof(skins[i].records));
|
||||
}
|
||||
|
||||
unloaded_skin_t *unloadedskin, *nextunloadedskin = NULL;
|
||||
for (unloadedskin = unloadedskins; unloadedskin; unloadedskin = nextunloadedskin)
|
||||
{
|
||||
nextunloadedskin = unloadedskin->next;
|
||||
Z_Free(unloadedskin);
|
||||
}
|
||||
unloadedskins = NULL;
|
||||
|
||||
// We retain exclusively the most important stuff from maps.
|
||||
|
||||
UINT8 restoremapvisited;
|
||||
recordtimes_t restoretimeattack;
|
||||
recordtimes_t restorespbattack;
|
||||
|
||||
for (i = 0; i < nummapheaders; i++)
|
||||
{
|
||||
restoremapvisited = mapheaderinfo[i]->records.mapvisited;
|
||||
restoretimeattack = mapheaderinfo[i]->records.timeattack;
|
||||
restorespbattack = mapheaderinfo[i]->records.spbattack;
|
||||
|
||||
memset(&mapheaderinfo[i]->records, 0, sizeof(recorddata_t));
|
||||
|
||||
mapheaderinfo[i]->records.mapvisited = restoremapvisited;
|
||||
mapheaderinfo[i]->records.timeattack = restoretimeattack;
|
||||
mapheaderinfo[i]->records.spbattack = restorespbattack;
|
||||
}
|
||||
|
||||
unloaded_mapheader_t *unloadedmap;
|
||||
for (unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = unloadedmap->next)
|
||||
{
|
||||
restoremapvisited = unloadedmap->records.mapvisited;
|
||||
restoretimeattack = unloadedmap->records.timeattack;
|
||||
restorespbattack = unloadedmap->records.spbattack;
|
||||
|
||||
memset(&unloadedmap->records, 0, sizeof(recorddata_t));
|
||||
|
||||
unloadedmap->records.mapvisited = restoremapvisited;
|
||||
unloadedmap->records.timeattack = restoretimeattack;
|
||||
unloadedmap->records.spbattack = restorespbattack;
|
||||
}
|
||||
}
|
||||
|
||||
void M_ClearSecrets(void)
|
||||
|
|
@ -707,6 +756,8 @@ void M_ClearSecrets(void)
|
|||
if (!mapheaderinfo[i])
|
||||
continue;
|
||||
|
||||
mapheaderinfo[i]->records.mapvisited = 0;
|
||||
|
||||
mapheaderinfo[i]->cache_spraycan = UINT16_MAX;
|
||||
|
||||
mapheaderinfo[i]->cache_maplock = MAXUNLOCKABLES;
|
||||
|
|
@ -2972,6 +3023,11 @@ char *M_BuildConditionSetString(UINT16 unlockid)
|
|||
}
|
||||
}
|
||||
|
||||
if (usedTourney && unlockables[unlockid].conditionset == 55 && gamedata->unlocked[unlockid] == false)
|
||||
{
|
||||
strcpy(message, "Power shrouds this challenge in darkness... (Return here without Tournament Mode!)\0");
|
||||
}
|
||||
|
||||
// Finally, do a clean wordwrap!
|
||||
return V_ScaledWordWrap(
|
||||
DESCRIPTIONWIDTH << FRACBITS,
|
||||
|
|
|
|||
20
src/m_pw.cpp
20
src/m_pw.cpp
|
|
@ -110,6 +110,8 @@ void f_tournament()
|
|||
{
|
||||
if (!unlockables[i].conditionset)
|
||||
continue;
|
||||
if (unlockables[i].conditionset == 55)
|
||||
continue;
|
||||
if (gamedata->unlocked[i])
|
||||
continue;
|
||||
|
||||
|
|
@ -146,10 +148,12 @@ void f_tournament()
|
|||
S_StartSound(0, sfx_kc42);
|
||||
|
||||
text = M_GetText(
|
||||
"All challenges temporarily unlocked.\n"
|
||||
"Unlocked\x83 almost\x80 everything.\n"
|
||||
"Saving is disabled - the game will\n"
|
||||
"return to normal on next launch.\n"
|
||||
);
|
||||
|
||||
usedTourney = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -158,18 +162,20 @@ void f_tournament()
|
|||
if (usedCheats)
|
||||
{
|
||||
text = M_GetText(
|
||||
"This is the correct password, but\n"
|
||||
"you already have every challenge\n"
|
||||
"unlocked, so nothing has changed.\n"
|
||||
"This is the correct password,\n"
|
||||
"but there's nothing to unlock\n"
|
||||
"right now -- nothing has changed.\n"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = M_GetText(
|
||||
"This is the correct password, but\n"
|
||||
"you already have every challenge\n"
|
||||
"unlocked, so saving is still allowed!\n"
|
||||
"there's nothing to unlock right\n"
|
||||
"now, so saving is still allowed!\n"
|
||||
);
|
||||
|
||||
usedTourney = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -308,7 +314,7 @@ try_password_e M_TryPassword(const char *password, boolean conditions)
|
|||
add_job(pw.hash_.data(), &pw);
|
||||
|
||||
// Only consider challenges passwords as needed.
|
||||
if (conditions)
|
||||
if (conditions && !usedTourney)
|
||||
iter_conditions([&](condition_t* cn) { add_job((const UINT8*)cn->stringvar, cn); });
|
||||
|
||||
try_password_e return_code = M_PW_INVALID;
|
||||
|
|
|
|||
|
|
@ -847,7 +847,7 @@ boolean M_ChallengesInputs(INT32 ch)
|
|||
{
|
||||
M_ChallengesTutorial(CCTUTORIAL_MAJORSKIP);
|
||||
}
|
||||
else if (M_CanKeyHiliTile())
|
||||
else if (M_CanKeyHiliTile() && !usedTourney)
|
||||
{
|
||||
challengesmenu.chaokeyhold = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@ menuitem_t OPTIONS_Gameplay[] =
|
|||
{IT_STRING | IT_CVAR, "Game Speed", "Gear for the next map.",
|
||||
NULL, {.cvar = &cv_kartspeed}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CVAR, "Base Lap Count", "How many laps must be completed per race.",
|
||||
NULL, {.cvar = &cv_numlaps}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CVAR, "Frantic Items", "Make item odds crazier with more powerful items!",
|
||||
NULL, {.cvar = &cv_kartfrantic}, 0, 0},
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "../k_battle.h"
|
||||
#include "../m_random.h"
|
||||
#include "../k_specialstage.h" // specialstageinfo
|
||||
#include "../k_kart.h"
|
||||
|
||||
#define FLOAT_HEIGHT ( 12 * FRACUNIT )
|
||||
#define FLOAT_TIME ( 2 * TICRATE )
|
||||
|
|
@ -122,7 +123,7 @@ void Obj_RandomItemVisuals(mobj_t *mobj)
|
|||
// the player's cleared out a good portion of the map.
|
||||
//
|
||||
// Then extraval1 starts ticking up and triggers the transformation from Ringbox to Random Item.
|
||||
if (mobj->fuse == 0 && !(mobj->flags & MF_NOCLIPTHING) && !(mobj->flags2 & MF2_BOSSDEAD) && !cv_thunderdome.value
|
||||
if (mobj->fuse == 0 && !(mobj->flags & MF_NOCLIPTHING) && !(mobj->flags2 & MF2_BOSSDEAD) && !K_ThunderDome()
|
||||
&& (modeattacking == ATTACKING_NONE || !!(modeattacking & ATTACKING_SPB) || specialstageinfo.valid)) // Time Attacking in Special is a fucked-looking exception
|
||||
{
|
||||
mobj->extravalue1++;
|
||||
|
|
|
|||
|
|
@ -1244,9 +1244,10 @@ static mobj_t *InitSpecialUFO(waypoint_t *start)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Prize -- todo, currently using standard Emerald
|
||||
// Prize -- todo, currently using fake Emerald
|
||||
P_SetMobjState(emerald, S_CHAOSEMERALD1);
|
||||
P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER);
|
||||
emerald->color = SKINCOLOR_GOLD;
|
||||
}
|
||||
|
||||
P_SetTarget(&emerald->target, ufo);
|
||||
|
|
|
|||
|
|
@ -1525,7 +1525,7 @@ boolean P_CheckRacers(void)
|
|||
{
|
||||
const boolean griefed = (spectateGriefed > 0);
|
||||
|
||||
boolean eliminateLast = cv_karteliminatelast.value;
|
||||
boolean eliminateLast = (!K_CanChangeRules(true) || (cv_karteliminatelast.value != 0));
|
||||
boolean allHumansDone = true;
|
||||
//boolean allBotsDone = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -274,6 +274,10 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEINT16(save->p, players[i].totalring);
|
||||
WRITEUINT32(save->p, players[i].realtime);
|
||||
for (j = 0; j < LAP__MAX; j++)
|
||||
{
|
||||
WRITEUINT32(save->p, players[i].laptime[j]);
|
||||
}
|
||||
WRITEUINT8(save->p, players[i].laps);
|
||||
WRITEUINT8(save->p, players[i].latestlap);
|
||||
WRITEUINT32(save->p, players[i].lapPoints);
|
||||
|
|
@ -910,6 +914,10 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
players[i].totalring = READINT16(save->p); // Total number of rings obtained for GP
|
||||
players[i].realtime = READUINT32(save->p); // integer replacement for leveltime
|
||||
for (j = 0; j < LAP__MAX; j++)
|
||||
{
|
||||
players[i].laptime[j] = READUINT32(save->p);
|
||||
}
|
||||
players[i].laps = READUINT8(save->p); // Number of laps (optional)
|
||||
players[i].latestlap = READUINT8(save->p);
|
||||
players[i].lapPoints = READUINT32(save->p);
|
||||
|
|
|
|||
|
|
@ -7675,7 +7675,6 @@ static void P_InitLevelSettings(void)
|
|||
}
|
||||
|
||||
racecountdown = exitcountdown = musiccountdown = exitfadestarted = 0;
|
||||
curlap = bestlap = 0; // SRB2Kart
|
||||
|
||||
g_exit.losing = false;
|
||||
g_exit.retry = false;
|
||||
|
|
|
|||
14
src/p_spec.c
14
src/p_spec.c
|
|
@ -2094,16 +2094,14 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
if (player->laps > 1)
|
||||
{
|
||||
// save best lap for record attack
|
||||
if (modeattacking && player == &players[consoleplayer])
|
||||
if (player->laptime[LAP_CUR] < player->laptime[LAP_BEST] || player->laptime[LAP_BEST] == 0)
|
||||
{
|
||||
if (curlap < bestlap || bestlap == 0)
|
||||
{
|
||||
bestlap = curlap;
|
||||
}
|
||||
|
||||
curlap = 0;
|
||||
player->laptime[LAP_BEST] = player->laptime[LAP_CUR];
|
||||
}
|
||||
|
||||
player->laptime[LAP_LAST] = player->laptime[LAP_CUR];
|
||||
player->laptime[LAP_CUR] = 0;
|
||||
|
||||
// Update power levels for this lap.
|
||||
K_UpdatePowerLevels(player, player->laps, false);
|
||||
|
||||
|
|
@ -2223,7 +2221,7 @@ static void K_HandleLapDecrement(player_t *player)
|
|||
player->cheatchecknum = numcheatchecks;
|
||||
player->laps--;
|
||||
K_UpdateAllPlayerPositions();
|
||||
curlap = UINT32_MAX;
|
||||
player->laptime[LAP_CUR] = UINT32_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
15
src/p_user.c
15
src/p_user.c
|
|
@ -4322,19 +4322,16 @@ void P_PlayerThink(player_t *player)
|
|||
if (leveltime >= starttime)
|
||||
{
|
||||
player->realtime = leveltime - starttime;
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
if (player->spectator)
|
||||
curlap = 0;
|
||||
else if (curlap != UINT32_MAX)
|
||||
curlap++; // This is too complicated to sync to realtime, just sorta hope for the best :V
|
||||
}
|
||||
|
||||
if (player->spectator)
|
||||
player->laptime[LAP_CUR] = 0;
|
||||
else if (player->laptime[LAP_CUR] != UINT32_MAX)
|
||||
player->laptime[LAP_CUR]++; // This is too complicated to sync to realtime, just sorta hope for the best :V
|
||||
}
|
||||
else
|
||||
{
|
||||
player->realtime = 0;
|
||||
if (player == &players[consoleplayer])
|
||||
curlap = 0;
|
||||
player->laptime[LAP_CUR] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue