Add K_CanChangeRules, and start a "single session" GP when warping to a map in single player

This commit is contained in:
Sally Coolatta 2020-06-06 19:45:13 -04:00
parent 76b41f5a3b
commit 136bb1d252
11 changed files with 262 additions and 67 deletions

View file

@ -1136,7 +1136,24 @@ void D_SRB2Main(void)
else else
{ {
if (!M_CheckParm("-server")) if (!M_CheckParm("-server"))
{
G_SetGameModified(true, true); G_SetGameModified(true, true);
// Start up a "minor" grand prix session
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
grandprixinfo.gamespeed = KARTSPEED_NORMAL;
grandprixinfo.encore = false;
grandprixinfo.masterbots = false;
grandprixinfo.gp = true;
grandprixinfo.roundnum = 0;
grandprixinfo.cup = NULL;
grandprixinfo.wonround = false;
grandprixinfo.initalize = true;
}
autostart = true; autostart = true;
} }
} }
@ -1519,18 +1536,46 @@ void D_SRB2Main(void)
INT16 newskill = -1; INT16 newskill = -1;
const char *sskill = M_GetNextParm(); const char *sskill = M_GetNextParm();
for (j = 0; kartspeed_cons_t[j].strvalue; j++) const UINT8 master = KARTSPEED_HARD+1;
if (!strcasecmp(kartspeed_cons_t[j].strvalue, sskill)) const char *masterstr = "Master";
if (!strcasecmp(masterstr, sskill))
{
newskill = master;
}
else
{
for (j = 0; kartspeed_cons_t[j].strvalue; j++)
{ {
newskill = (INT16)kartspeed_cons_t[j].value; if (!strcasecmp(kartspeed_cons_t[j].strvalue, sskill))
break; {
newskill = (INT16)kartspeed_cons_t[j].value;
break;
}
} }
if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match
{
j = atoi(sskill); // assume they gave us a skill number, which is okay too
if (j >= KARTSPEED_EASY && j <= master)
newskill = (INT16)j;
}
}
if (grandprixinfo.gp == true)
{ {
j = atoi(sskill); // assume they gave us a skill number, which is okay too if (newskill == master)
if (j >= KARTSPEED_EASY && j <= KARTSPEED_HARD) {
newskill = (INT16)j; grandprixinfo.masterbots = true;
newskill = KARTSPEED_HARD;
}
grandprixinfo.gamespeed = newskill;
}
else if (newskill == master)
{
grandprixinfo.masterbots = true;
newskill = KARTSPEED_HARD;
} }
if (newskill != -1) if (newskill != -1)

View file

@ -2769,7 +2769,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
if (netgame || multiplayer) if (netgame || multiplayer)
FLS = false; FLS = false;
if (grandprixinfo.roundnum != 0) if (grandprixinfo.gp == true)
{ {
// Too lazy to change the input value for every instance of this function....... // Too lazy to change the input value for every instance of this function.......
pencoremode = grandprixinfo.encore; pencoremode = grandprixinfo.encore;
@ -2922,6 +2922,7 @@ static void Command_Map_f(void)
INT32 newmapnum; INT32 newmapnum;
boolean newresetplayers, newencoremode; boolean newresetplayers, newencoremode;
INT32 newgametype = gametype; INT32 newgametype = gametype;
boolean startgp = false;
// max length of command: map map03 -gametype race -noresetplayers -force -encore // max length of command: map map03 -gametype race -noresetplayers -force -encore
// 1 2 3 4 5 6 7 // 1 2 3 4 5 6 7
@ -2952,6 +2953,7 @@ static void Command_Map_f(void)
if (COM_CheckParm("-force")) if (COM_CheckParm("-force"))
{ {
G_SetGameModified(false, true); G_SetGameModified(false, true);
startgp = true;
} }
else else
{ {
@ -3044,6 +3046,69 @@ static void Command_Map_f(void)
return; return;
} }
if (startgp)
{
i = COM_CheckParm("-skill");
grandprixinfo.gamespeed = (cv_kartspeed.value == KARTSPEED_AUTO ? KARTSPEED_NORMAL : cv_kartspeed.value);
grandprixinfo.masterbots = false;
if (i)
{
const UINT8 master = KARTSPEED_HARD+1;
const char *masterstr = "Master";
const char *skillname = COM_Argv(i+1);
INT32 newskill = -1;
INT32 j;
if (!strcasecmp(masterstr, skillname))
{
newskill = master;
}
else
{
for (j = 0; kartspeed_cons_t[j].strvalue; j++)
{
if (!strcasecmp(kartspeed_cons_t[j].strvalue, skillname))
{
newskill = (INT16)kartspeed_cons_t[j].value;
break;
}
}
if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match
{
j = atoi(COM_Argv(i+1)); // assume they gave us a skill number, which is okay too
if (j >= KARTSPEED_EASY && j <= master)
newskill = (INT16)j;
}
}
if (newskill != -1)
{
if (newskill == master)
{
grandprixinfo.gamespeed = KARTSPEED_HARD;
grandprixinfo.masterbots = true;
}
else
{
grandprixinfo.gamespeed = newskill;
grandprixinfo.masterbots = false;
}
}
}
grandprixinfo.encore = newencoremode;
grandprixinfo.gp = true;
grandprixinfo.roundnum = 0;
grandprixinfo.cup = NULL;
grandprixinfo.wonround = false;
grandprixinfo.initalize = true;
}
fromlevelselect = false; fromlevelselect = false;
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false); D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false);
} }
@ -5067,14 +5132,16 @@ static void PointLimit_OnChange(void)
static void NumLaps_OnChange(void) static void NumLaps_OnChange(void)
{ {
if (!G_RaceGametype() || (modeattacking || demo.playback)) if (K_CanChangeRules() == false)
{
return; return;
}
if (server && Playing() if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
&& (netgame || multiplayer) && (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
&& (mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) {
&& (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps); CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
}
// Just don't be verbose // Just don't be verbose
CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value); CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value);
@ -5707,7 +5774,7 @@ void Command_Retry_f(void)
{ {
CONS_Printf(M_GetText("You must be in a level to use this.\n")); CONS_Printf(M_GetText("You must be in a level to use this.\n"));
} }
else if (netgame || grandprixinfo.roundnum == 0) else if (grandprixinfo.gp == false)
{ {
CONS_Printf(M_GetText("This only works in Grand Prix.\n")); CONS_Printf(M_GetText("This only works in Grand Prix.\n"));
} }
@ -6201,24 +6268,35 @@ static void Command_ShowTime_f(void)
// SRB2Kart: On change messages // SRB2Kart: On change messages
static void BaseNumLaps_OnChange(void) static void BaseNumLaps_OnChange(void)
{ {
if (gamestate == GS_LEVEL && grandprixinfo.roundnum == 0) if (K_CanChangeRules() == true)
{ {
if (cv_basenumlaps.value) const char *str = va("%d", cv_basenumlaps.value);
CONS_Printf(M_GetText("Number of laps will be changed to %d next round.\n"), cv_basenumlaps.value);
else if (cv_basenumlaps.value == 0)
CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n")); {
str = "map defaults";
}
CONS_Printf(M_GetText("Number of laps will be changed to %s next round.\n"), str);
} }
} }
static void KartFrantic_OnChange(void) static void KartFrantic_OnChange(void)
{ {
if ((boolean)cv_kartfrantic.value != franticitems && gamestate == GS_LEVEL && leveltime > starttime) if (K_CanChangeRules() == false)
CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off")); {
return;
}
if (leveltime < starttime)
{
CONS_Printf(M_GetText("Frantic items has been set to %s.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
franticitems = (boolean)cv_kartfrantic.value;
}
else else
{ {
CONS_Printf(M_GetText("Frantic items has been turned %s.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off")); CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
franticitems = (boolean)cv_kartfrantic.value;
} }
} }
@ -6231,47 +6309,59 @@ static void KartSpeed_OnChange(void)
return; return;
} }
if (G_RaceGametype() && grandprixinfo.roundnum == 0) if (K_CanChangeRules() == false)
{ {
if ((gamestate == GS_LEVEL && leveltime < starttime) && (cv_kartspeed.value != KARTSPEED_AUTO)) return;
{ }
CONS_Printf(M_GetText("Game speed has been changed to \"%s\".\n"), cv_kartspeed.string);
gamespeed = (UINT8)cv_kartspeed.value; if (leveltime < starttime && cv_kartspeed.value != KARTSPEED_AUTO)
} {
else if (cv_kartspeed.value != (signed)gamespeed) CONS_Printf(M_GetText("Game speed has been changed to \"%s\".\n"), cv_kartspeed.string);
{ gamespeed = (UINT8)cv_kartspeed.value;
CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string); }
} else
{
CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string);
} }
} }
static void KartEncore_OnChange(void) static void KartEncore_OnChange(void)
{ {
if (G_RaceGametype() && grandprixinfo.roundnum == 0) if (K_CanChangeRules() == false)
{ {
if ((cv_kartencore.value == 1) != encoremode && gamestate == GS_LEVEL /*&& leveltime > starttime*/) return;
CONS_Printf(M_GetText("Encore Mode will be set to %s next round.\n"), cv_kartencore.string);
else
CONS_Printf(M_GetText("Encore Mode has been set to %s.\n"), cv_kartencore.string);
} }
CONS_Printf(M_GetText("Encore Mode will be set to %s next round.\n"), cv_kartencore.string);
} }
static void KartComeback_OnChange(void) static void KartComeback_OnChange(void)
{ {
if (G_BattleGametype()) if (K_CanChangeRules() == false)
{ {
if ((boolean)cv_kartcomeback.value != comeback && gamestate == GS_LEVEL && leveltime > starttime) return;
CONS_Printf(M_GetText("Karma Comeback will be turned %s next round.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off")); }
else
{ if (leveltime < starttime)
CONS_Printf(M_GetText("Karma Comeback has been turned %s.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off")); {
comeback = (boolean)cv_kartcomeback.value; CONS_Printf(M_GetText("Karma Comeback has been turned %s.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off"));
} comeback = (boolean)cv_kartcomeback.value;
}
else
{
CONS_Printf(M_GetText("Karma Comeback will be turned %s next round.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off"));
} }
} }
static void KartEliminateLast_OnChange(void) static void KartEliminateLast_OnChange(void)
{ {
if (G_RaceGametype() && cv_karteliminatelast.value && grandprixinfo.roundnum == 0) if (K_CanChangeRules() == false)
{
CV_StealthSet(&cv_karteliminatelast, cv_karteliminatelast.defaultvalue);
}
if (G_RaceGametype())
{
P_CheckRacers(); P_CheckRacers();
}
} }

View file

@ -3220,7 +3220,7 @@ void G_ExitLevel(void)
{ {
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
if (grandprixinfo.roundnum > 0 && grandprixinfo.wonround != true) if (grandprixinfo.gp == true && grandprixinfo.wonround != true)
{ {
UINT8 i; UINT8 i;
@ -3336,7 +3336,7 @@ boolean G_IsSpecialStage(INT32 mapnum)
// //
boolean G_GametypeUsesLives(void) boolean G_GametypeUsesLives(void)
{ {
if ((grandprixinfo.roundnum > 0) // In Grand Prix if ((grandprixinfo.gp == true) // In Grand Prix
&& (gametype == GT_RACE) // NOT in bonus round && (gametype == GT_RACE) // NOT in bonus round
&& !(modeattacking) // NOT in Record Attack && !(modeattacking) // NOT in Record Attack
&& !G_IsSpecialStage(gamemap)) // NOT in special stage && !G_IsSpecialStage(gamemap)) // NOT in special stage
@ -3734,16 +3734,24 @@ static void G_DoCompleted(void)
{ {
nextmap = (INT16)(nextmapoverride-1); nextmap = (INT16)(nextmapoverride-1);
} }
else if (grandprixinfo.roundnum != 0) else if (grandprixinfo.gp == true)
{ {
if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) if (grandprixinfo.roundnum == 0 || grandprixinfo.cup == NULL) // Single session
{ {
nextmap = 1101; // ceremonymap nextmap = prevmap; // Same map
} }
else else
{ {
nextmap = grandprixinfo.cup->levellist[grandprixinfo.roundnum]; if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) // On final map
grandprixinfo.roundnum++; {
nextmap = 1101; // ceremonymap
}
else
{
// Proceed to next map
nextmap = grandprixinfo.cup->levellist[grandprixinfo.roundnum];
grandprixinfo.roundnum++;
}
} }
} }
else else
@ -3759,7 +3767,7 @@ static void G_DoCompleted(void)
// a map of the proper gametype -- skip levels that don't support // a map of the proper gametype -- skip levels that don't support
// the current gametype. (Helps avoid playing boss levels in Race, // the current gametype. (Helps avoid playing boss levels in Race,
// for instance). // for instance).
if (!modeattacking && (grandprixinfo.roundnum == 0) && (nextmap >= 0 && nextmap < NUMMAPS)) if (!modeattacking && grandprixinfo.gp == false && (nextmap >= 0 && nextmap < NUMMAPS))
{ {
register INT16 cm = nextmap; register INT16 cm = nextmap;
INT16 tolflag = G_TOLFlag(gametype); INT16 tolflag = G_TOLFlag(gametype);
@ -3883,7 +3891,7 @@ void G_NextLevel(void)
{ {
if (gamestate != GS_VOTING) if (gamestate != GS_VOTING)
{ {
if ((cv_advancemap.value == 3) && grandprixinfo.roundnum == 0 && !modeattacking && !skipstats && (multiplayer || netgame)) if ((cv_advancemap.value == 3) && grandprixinfo.gp == false && !modeattacking && !skipstats && (multiplayer || netgame))
{ {
UINT8 i; UINT8 i;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)

View file

@ -280,11 +280,17 @@ static INT16 K_RivalScore(player_t *bot)
{ {
const UINT16 difficulty = bot->botvars.difficulty; const UINT16 difficulty = bot->botvars.difficulty;
const UINT16 score = bot->score; const UINT16 score = bot->score;
const SINT8 roundsleft = grandprixinfo.cup->numlevels - grandprixinfo.roundnum; SINT8 roundnum = 1, roundsleft = 1;
UINT16 lowestscore = UINT16_MAX; UINT16 lowestscore = UINT16_MAX;
UINT8 lowestdifficulty = MAXBOTDIFFICULTY; UINT8 lowestdifficulty = MAXBOTDIFFICULTY;
UINT8 i; UINT8 i;
if (grandprixinfo.cup != NULL)
{
roundnum = grandprixinfo.roundnum;
roundsleft = grandprixinfo.cup->numlevels - grandprixinfo.roundnum;
}
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!playeringame[i] || players[i].spectator)
@ -307,7 +313,7 @@ static INT16 K_RivalScore(player_t *bot)
// This will try to influence the higher difficulty bots to get rival more often & get even more points. // This will try to influence the higher difficulty bots to get rival more often & get even more points.
// However, when we're running low on matches left, we need to focus more on raw score! // However, when we're running low on matches left, we need to focus more on raw score!
return ((difficulty - lowestdifficulty) * roundsleft) + ((score - lowestscore) * grandprixinfo.roundnum); return ((difficulty - lowestdifficulty) * roundsleft) + ((score - lowestscore) * roundnum);
} }
/*-------------------------------------------------- /*--------------------------------------------------
@ -569,3 +575,31 @@ void K_PlayerLoseLife(player_t *player)
} }
#endif #endif
} }
/*--------------------------------------------------
boolean K_CanChangeRules(void)
See header file for description.
--------------------------------------------------*/
boolean K_CanChangeRules(void)
{
if (demo.playback)
{
// We've already got our important settings!
return false;
}
if (grandprixinfo.gp == true && grandprixinfo.roundnum > 0)
{
// Don't cheat the rules of the GP!
return false;
}
if (modeattacking == true)
{
// Don't cheat the rules of Time Trials!
return false;
}
return true;
}

View file

@ -18,7 +18,8 @@
extern struct grandprixinfo extern struct grandprixinfo
{ {
UINT8 roundnum; ///< Round number -- if 0, then we're not in a Grand Prix. boolean gp; ///< If true, then we are in a Grand Prix.
UINT8 roundnum; ///< Round number. If 0, this is a single session from the warp command.
cupheader_t *cup; ///< Which cup are we playing? cupheader_t *cup; ///< Which cup are we playing?
UINT8 gamespeed; ///< Copy of gamespeed, just to make sure you can't cheat it with cvars UINT8 gamespeed; ///< Copy of gamespeed, just to make sure you can't cheat it with cvars
boolean encore; ///< Ditto, but for encore mode boolean encore; ///< Ditto, but for encore mode
@ -124,4 +125,20 @@ void K_FakeBotResults(player_t *bot);
void K_PlayerLoseLife(player_t *player); void K_PlayerLoseLife(player_t *player);
/*--------------------------------------------------
boolean K_CanChangeRules(void);
Returns whenver or not the server is allowed
to change the game rules.
Input Arguments:-
None
Return:-
None
--------------------------------------------------*/
boolean K_CanChangeRules(void);
#endif #endif

View file

@ -30,7 +30,7 @@ SINT8 K_UsingPowerLevels(void)
{ {
SINT8 pt = PWRLV_DISABLED; SINT8 pt = PWRLV_DISABLED;
if (!cv_kartusepwrlv.value || !netgame || grandprixinfo.roundnum > 0) if (!cv_kartusepwrlv.value || !netgame || grandprixinfo.gp == true)
{ {
return PWRLV_DISABLED; return PWRLV_DISABLED;
} }

View file

@ -7649,6 +7649,7 @@ static void M_StartGrandPrix(INT32 choice)
grandprixinfo.cup = gpcup; grandprixinfo.cup = gpcup;
grandprixinfo.gp = true;
grandprixinfo.roundnum = 1; grandprixinfo.roundnum = 1;
grandprixinfo.wonround = false; grandprixinfo.wonround = false;

View file

@ -2028,7 +2028,7 @@ boolean P_CheckRacers(void)
} }
else else
{ {
if (grandprixinfo.roundnum > 0) if (grandprixinfo.gp == true)
{ {
// Always do this in GP // Always do this in GP
eliminatelast = true; eliminatelast = true;

View file

@ -2418,7 +2418,7 @@ static void P_LevelInitStuff(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (grandprixinfo.roundnum == 0) if (grandprixinfo.gp == false)
{ {
players[i].lives = 3; players[i].lives = 3;
players[i].xtralife = 0; players[i].xtralife = 0;
@ -2465,7 +2465,7 @@ static void P_LevelInitStuff(void)
} }
// SRB2Kart: map load variables // SRB2Kart: map load variables
if (grandprixinfo.roundnum != 0) if (grandprixinfo.gp == true)
{ {
if (G_BattleGametype()) if (G_BattleGametype())
{ {
@ -3389,7 +3389,7 @@ boolean P_SetupLevel(boolean skipprecip)
// NOW you can try to spawn in the Battle capsules, if there's not enough players for a match // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match
K_SpawnBattleCapsules(); K_SpawnBattleCapsules();
if (grandprixinfo.roundnum != 0) if (grandprixinfo.gp == true)
{ {
if (grandprixinfo.initalize == true) if (grandprixinfo.initalize == true)
{ {

View file

@ -1739,7 +1739,7 @@ void P_DoPlayerExit(player_t *player)
else else
player->exiting = raceexittime+2; // Accidental death safeguard??? player->exiting = raceexittime+2; // Accidental death safeguard???
if (grandprixinfo.roundnum > 0) if (grandprixinfo.gp == true)
{ {
if (player->bot) if (player->bot)
{ {

View file

@ -645,7 +645,7 @@ void Y_IntermissionDrawer(void)
} }
dotimer: dotimer:
if (timer && grandprixinfo.roundnum == 0) if (timer && grandprixinfo.gp == false)
{ {
char *string; char *string;
INT32 tickdown = (timer+1)/TICRATE; INT32 tickdown = (timer+1)/TICRATE;