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
{
if (!M_CheckParm("-server"))
{
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;
}
}
@ -1519,18 +1536,46 @@ void D_SRB2Main(void)
INT16 newskill = -1;
const char *sskill = M_GetNextParm();
for (j = 0; kartspeed_cons_t[j].strvalue; j++)
if (!strcasecmp(kartspeed_cons_t[j].strvalue, sskill))
const UINT8 master = KARTSPEED_HARD+1;
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;
break;
if (!strcasecmp(kartspeed_cons_t[j].strvalue, sskill))
{
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 (j >= KARTSPEED_EASY && j <= KARTSPEED_HARD)
newskill = (INT16)j;
if (newskill == master)
{
grandprixinfo.masterbots = true;
newskill = KARTSPEED_HARD;
}
grandprixinfo.gamespeed = newskill;
}
else if (newskill == master)
{
grandprixinfo.masterbots = true;
newskill = KARTSPEED_HARD;
}
if (newskill != -1)

View file

@ -2769,7 +2769,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
if (netgame || multiplayer)
FLS = false;
if (grandprixinfo.roundnum != 0)
if (grandprixinfo.gp == true)
{
// Too lazy to change the input value for every instance of this function.......
pencoremode = grandprixinfo.encore;
@ -2922,6 +2922,7 @@ static void Command_Map_f(void)
INT32 newmapnum;
boolean newresetplayers, newencoremode;
INT32 newgametype = gametype;
boolean startgp = false;
// max length of command: map map03 -gametype race -noresetplayers -force -encore
// 1 2 3 4 5 6 7
@ -2952,6 +2953,7 @@ static void Command_Map_f(void)
if (COM_CheckParm("-force"))
{
G_SetGameModified(false, true);
startgp = true;
}
else
{
@ -3044,6 +3046,69 @@ static void Command_Map_f(void)
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;
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false);
}
@ -5067,14 +5132,16 @@ static void PointLimit_OnChange(void)
static void NumLaps_OnChange(void)
{
if (!G_RaceGametype() || (modeattacking || demo.playback))
if (K_CanChangeRules() == false)
{
return;
}
if (server && Playing()
&& (netgame || multiplayer)
&& (mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
&& (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
&& (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
{
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
}
// Just don't be verbose
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"));
}
else if (netgame || grandprixinfo.roundnum == 0)
else if (grandprixinfo.gp == false)
{
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
static void BaseNumLaps_OnChange(void)
{
if (gamestate == GS_LEVEL && grandprixinfo.roundnum == 0)
if (K_CanChangeRules() == true)
{
if (cv_basenumlaps.value)
CONS_Printf(M_GetText("Number of laps will be changed to %d next round.\n"), cv_basenumlaps.value);
else
CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n"));
const char *str = va("%d", cv_basenumlaps.value);
if (cv_basenumlaps.value == 0)
{
str = "map defaults";
}
CONS_Printf(M_GetText("Number of laps will be changed to %s next round.\n"), str);
}
}
static void KartFrantic_OnChange(void)
{
if ((boolean)cv_kartfrantic.value != franticitems && gamestate == GS_LEVEL && leveltime > starttime)
CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
if (K_CanChangeRules() == false)
{
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
{
CONS_Printf(M_GetText("Frantic items has been turned %s.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
franticitems = (boolean)cv_kartfrantic.value;
CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
}
}
@ -6231,47 +6309,59 @@ static void KartSpeed_OnChange(void)
return;
}
if (G_RaceGametype() && grandprixinfo.roundnum == 0)
if (K_CanChangeRules() == false)
{
if ((gamestate == GS_LEVEL && leveltime < starttime) && (cv_kartspeed.value != KARTSPEED_AUTO))
{
CONS_Printf(M_GetText("Game speed has been changed to \"%s\".\n"), cv_kartspeed.string);
gamespeed = (UINT8)cv_kartspeed.value;
}
else if (cv_kartspeed.value != (signed)gamespeed)
{
CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string);
}
return;
}
if (leveltime < starttime && cv_kartspeed.value != KARTSPEED_AUTO)
{
CONS_Printf(M_GetText("Game speed has been changed to \"%s\".\n"), cv_kartspeed.string);
gamespeed = (UINT8)cv_kartspeed.value;
}
else
{
CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string);
}
}
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*/)
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);
return;
}
CONS_Printf(M_GetText("Encore Mode will be set to %s next round.\n"), cv_kartencore.string);
}
static void KartComeback_OnChange(void)
{
if (G_BattleGametype())
if (K_CanChangeRules() == false)
{
if ((boolean)cv_kartcomeback.value != comeback && gamestate == GS_LEVEL && leveltime > starttime)
CONS_Printf(M_GetText("Karma Comeback will be turned %s next round.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off"));
else
{
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;
}
return;
}
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;
}
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)
{
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();
}
}

View file

@ -3220,7 +3220,7 @@ void G_ExitLevel(void)
{
if (gamestate == GS_LEVEL)
{
if (grandprixinfo.roundnum > 0 && grandprixinfo.wonround != true)
if (grandprixinfo.gp == true && grandprixinfo.wonround != true)
{
UINT8 i;
@ -3336,7 +3336,7 @@ boolean G_IsSpecialStage(INT32 mapnum)
//
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
&& !(modeattacking) // NOT in Record Attack
&& !G_IsSpecialStage(gamemap)) // NOT in special stage
@ -3734,16 +3734,24 @@ static void G_DoCompleted(void)
{
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
{
nextmap = grandprixinfo.cup->levellist[grandprixinfo.roundnum];
grandprixinfo.roundnum++;
if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) // On final map
{
nextmap = 1101; // ceremonymap
}
else
{
// Proceed to next map
nextmap = grandprixinfo.cup->levellist[grandprixinfo.roundnum];
grandprixinfo.roundnum++;
}
}
}
else
@ -3759,7 +3767,7 @@ static void G_DoCompleted(void)
// a map of the proper gametype -- skip levels that don't support
// the current gametype. (Helps avoid playing boss levels in Race,
// for instance).
if (!modeattacking && (grandprixinfo.roundnum == 0) && (nextmap >= 0 && nextmap < NUMMAPS))
if (!modeattacking && grandprixinfo.gp == false && (nextmap >= 0 && nextmap < NUMMAPS))
{
register INT16 cm = nextmap;
INT16 tolflag = G_TOLFlag(gametype);
@ -3883,7 +3891,7 @@ void G_NextLevel(void)
{
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;
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 score = bot->score;
const SINT8 roundsleft = grandprixinfo.cup->numlevels - grandprixinfo.roundnum;
SINT8 roundnum = 1, roundsleft = 1;
UINT16 lowestscore = UINT16_MAX;
UINT8 lowestdifficulty = MAXBOTDIFFICULTY;
UINT8 i;
if (grandprixinfo.cup != NULL)
{
roundnum = grandprixinfo.roundnum;
roundsleft = grandprixinfo.cup->numlevels - grandprixinfo.roundnum;
}
for (i = 0; i < MAXPLAYERS; i++)
{
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.
// 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
}
/*--------------------------------------------------
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
{
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?
UINT8 gamespeed; ///< Copy of gamespeed, just to make sure you can't cheat it with cvars
boolean encore; ///< Ditto, but for encore mode
@ -124,4 +125,20 @@ void K_FakeBotResults(player_t *bot);
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

View file

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

View file

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

View file

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

View file

@ -2418,7 +2418,7 @@ static void P_LevelInitStuff(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (grandprixinfo.roundnum == 0)
if (grandprixinfo.gp == false)
{
players[i].lives = 3;
players[i].xtralife = 0;
@ -2465,7 +2465,7 @@ static void P_LevelInitStuff(void)
}
// SRB2Kart: map load variables
if (grandprixinfo.roundnum != 0)
if (grandprixinfo.gp == true)
{
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
K_SpawnBattleCapsules();
if (grandprixinfo.roundnum != 0)
if (grandprixinfo.gp == true)
{
if (grandprixinfo.initalize == true)
{

View file

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

View file

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