Merge branch 'menu-polish' into 'master'

Menu Polish

Closes #1048, #1183, and #1216

See merge request KartKrew/Kart!2187
This commit is contained in:
Oni 2024-03-31 05:52:19 +00:00
commit efdff207fd
17 changed files with 258 additions and 63 deletions

View file

@ -82,7 +82,7 @@ CV_PossibleValue_t CV_TrueFalse[] = {{0, "False"}, {1, "True"}, {0, NULL}};
// SRB2kart // SRB2kart
CV_PossibleValue_t kartspeed_cons_t[] = { CV_PossibleValue_t kartspeed_cons_t[] = {
{KARTSPEED_AUTO, "Auto"}, {KARTSPEED_AUTO, "Auto Gear"},
{KARTSPEED_EASY, "Gear 1"}, {KARTSPEED_EASY, "Gear 1"},
{KARTSPEED_NORMAL, "Gear 2"}, {KARTSPEED_NORMAL, "Gear 2"},
{KARTSPEED_HARD, "Gear 3"}, {KARTSPEED_HARD, "Gear 3"},

View file

@ -724,7 +724,7 @@ void KartFrantic_OnChange(void);
consvar_t cv_kartfrantic = UnsavedNetVar("franticitems", "Off").on_off().onchange_noinit(KartFrantic_OnChange); consvar_t cv_kartfrantic = UnsavedNetVar("franticitems", "Off").on_off().onchange_noinit(KartFrantic_OnChange);
void KartSpeed_OnChange(void); void KartSpeed_OnChange(void);
consvar_t cv_kartspeed = UnsavedNetVar("gamespeed", "Auto").values(kartspeed_cons_t).onchange_noinit(KartSpeed_OnChange); consvar_t cv_kartspeed = UnsavedNetVar("gamespeed", "Auto Gear").values(kartspeed_cons_t).onchange_noinit(KartSpeed_OnChange);
consvar_t cv_kartusepwrlv = UnsavedNetVar("usepwrlv", "Yes").yes_no(); consvar_t cv_kartusepwrlv = UnsavedNetVar("usepwrlv", "Yes").yes_no();

View file

@ -1105,7 +1105,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0'; netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0';
if (cv_kartusepwrlv.value) if (K_UsingPowerLevels() != PWRLV_DISABLED)
netbuffer->u.serverinfo.avgpwrlv = K_CalculatePowerLevelAvg(); netbuffer->u.serverinfo.avgpwrlv = K_CalculatePowerLevelAvg();
else else
netbuffer->u.serverinfo.avgpwrlv = -1; netbuffer->u.serverinfo.avgpwrlv = -1;
@ -1537,15 +1537,16 @@ static boolean SL_InsertServer(serverinfo_pak* info, SINT8 node)
i = SL_SearchServer(node); i = SL_SearchServer(node);
if (i == UINT32_MAX) if (i == UINT32_MAX)
{ {
// not found add it // not found, check for packet format rejections
if (serverlistcount >= MAXSERVERLIST) if (serverlistcount >= MAXSERVERLIST)
return false; // list full return false; // list full
if (info->_255 != 255) if (info->_255 != 255)
return false;/* old packet format */ return false; // old packet format
if (info->packetversion != PACKETVERSION) if (info->packetversion != PACKETVERSION)
return false;/* old new packet format */ return false; // old new packet format
if (info->version != VERSION) if (info->version != VERSION)
return false; // Not same version. return false; // Not same version.
@ -1554,16 +1555,40 @@ static boolean SL_InsertServer(serverinfo_pak* info, SINT8 node)
return false; // Close, but no cigar. return false; // Close, but no cigar.
if (strcmp(info->application, SRB2APPLICATION)) if (strcmp(info->application, SRB2APPLICATION))
return false;/* that's a different mod */ return false; // that's a different mod
}
if (serverlistultimatecount && info->modifiedgame != (mpmenu.room == 1)) const INT32 gtidentifier = G_GetGametypeByName(info->gametypename);
return false;/* CORE vs MODDED! But only on the server browser page. */ UINT8 gtcalc = GTCALC_RACE;
if (gtidentifier != GT_RACE)
{
gtcalc = (gtidentifier == GT_BATTLE) ? GTCALC_BATTLE : GTCALC_CUSTOM;
}
if (i == UINT32_MAX)
{
// Still not added to list... check for modifiedgame rejections
if (serverlistultimatecount)
{
// We're on the server browser page. We can reject based on our room.
if (
(
info->modifiedgame != false // self-declared
|| (gtcalc == GTCALC_CUSTOM) // not a main two gametype
) != (mpmenu.room == 1)
)
{
return false; // CORE vs MODDED!
}
}
// Ok, FINALLY now we can confirm
i = serverlistcount++; i = serverlistcount++;
} }
serverlist[i].info = *info; serverlist[i].info = *info;
serverlist[i].node = node; serverlist[i].node = node;
serverlist[i].cachedgtcalc = gtcalc;
// resort server list // resort server list
M_SortServerList(); M_SortServerList();
@ -2110,7 +2135,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{ {
I_OsPolling(); I_OsPolling();
// Needs to be updated here for M_DrawEggaChannel // Needs to be updated here for M_DrawEggaChannelAlignable
renderdeltatics = FRACUNIT; renderdeltatics = FRACUNIT;
rendertimefrac = FRACUNIT; rendertimefrac = FRACUNIT;
@ -2169,7 +2194,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{ {
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME) if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME)
{ {
M_DrawEggaChannel(); M_DrawEggaChannelAlignable(true);
} }
CL_DrawConnectionStatus(); CL_DrawConnectionStatus();

View file

@ -459,10 +459,14 @@ struct doomdata_t
#endif #endif
#define MAXSERVERLIST (MAXNETNODES-1) #define MAXSERVERLIST (MAXNETNODES-1)
#define GTCALC_RACE 0
#define GTCALC_BATTLE 1
#define GTCALC_CUSTOM 2
struct serverelem_t struct serverelem_t
{ {
SINT8 node; SINT8 node;
serverinfo_pak info; serverinfo_pak info;
UINT8 cachedgtcalc;
}; };
extern serverelem_t serverlist[MAXSERVERLIST]; extern serverelem_t serverlist[MAXSERVERLIST];

View file

@ -171,6 +171,7 @@ demoghost *ghosts = NULL;
#define DF_LUAVARS 0x20 // this demo contains extra lua vars #define DF_LUAVARS 0x20 // this demo contains extra lua vars
// woah there pardner, if you modify this check k_menu.h too
#define DF_ENCORE 0x40 #define DF_ENCORE 0x40
#define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode! #define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode!

View file

@ -241,7 +241,11 @@ void K_UpdateMatchRaceBots(void)
} }
grabskins[usableskins] = MAXSKINS; grabskins[usableskins] = MAXSKINS;
if ((gametyperules & GTR_BOTS) == 0 && !cv_forcebots.value) if (gamestate == GS_TITLESCREEN)
{
difficulty = 0;
}
else if ((gametyperules & GTR_BOTS) == 0 && !cv_forcebots.value)
{ {
difficulty = 0; difficulty = 0;
} }

View file

@ -385,8 +385,10 @@ typedef enum
sopt_sfxvolume, sopt_sfxvolume,
sopt_musicvolume, sopt_musicvolume,
sopt_spacer1, sopt_spacer1,
sopt_preferences,
sopt_chatnotifs, sopt_chatnotifs,
sopt_charvoices, sopt_charvoices,
sopt_followhorns,
sopt_attackmusic, sopt_attackmusic,
sopt_spacer2, sopt_spacer2,
sopt_advanced, sopt_advanced,
@ -1142,9 +1144,11 @@ void M_HandleProfileErase(INT32 choice);
void M_DrawMasterServerReminder(void); void M_DrawMasterServerReminder(void);
// Draws the EGGA CHANNEL background. // Draws the EGGA CHANNEL background.
void M_DrawEggaChannelAlignable(boolean centered);
void M_DrawEggaChannel(void); void M_DrawEggaChannel(void);
// Extras menu: // Extras menu:
// woah there pardner, if you modify this check g_demo.cpp too
#define DF_ENCORE 0x40 #define DF_ENCORE 0x40
#define M_EXTRAS_OFSTIME 4 #define M_EXTRAS_OFSTIME 4

View file

@ -2764,9 +2764,12 @@ static void M_DrawCupPreview(INT16 y, levelsearch_t *baselevelsearch)
UINT8 i = 0; UINT8 i = 0;
INT16 maxlevels = M_CountLevelsToShowInList(&locklesslevelsearch); INT16 maxlevels = M_CountLevelsToShowInList(&locklesslevelsearch);
const fixed_t step = (82 * FRACUNIT); const UINT32 ustep = 82;
fixed_t previewanimwork = (cupgrid.previewanim * FRACUNIT) + rendertimefrac_unpaused; const fixed_t fracstep = (ustep * FRACUNIT);
fixed_t x = -(previewanimwork % step);
UINT32 unsignedportion = 0;
fixed_t x = 0;
INT16 map, start = M_GetFirstLevelInList(&i, &locklesslevelsearch); INT16 map, start = M_GetFirstLevelInList(&i, &locklesslevelsearch);
UINT8 starti = i; UINT8 starti = i;
@ -2774,7 +2777,10 @@ static void M_DrawCupPreview(INT16 y, levelsearch_t *baselevelsearch)
if (baselevelsearch->cup && maxlevels > 0) if (baselevelsearch->cup && maxlevels > 0)
{ {
INT16 add = (previewanimwork / step) % maxlevels; unsignedportion = (cupgrid.previewanim % (maxlevels * ustep));
x = (unsignedportion * FRACUNIT) + rendertimefrac_unpaused;
INT16 add = (x / fracstep) % maxlevels;
map = start; map = start;
while (add > 0) while (add > 0)
{ {
@ -2787,6 +2793,8 @@ static void M_DrawCupPreview(INT16 y, levelsearch_t *baselevelsearch)
add--; add--;
} }
x = -(x % fracstep);
while (x < BASEVIDWIDTH * FRACUNIT) while (x < BASEVIDWIDTH * FRACUNIT)
{ {
if (map >= nummapheaders) if (map >= nummapheaders)
@ -2814,17 +2822,21 @@ static void M_DrawCupPreview(INT16 y, levelsearch_t *baselevelsearch)
NULL); NULL);
} }
x += step; x += fracstep;
map = M_GetNextLevelInList(map, &i, &locklesslevelsearch); map = M_GetNextLevelInList(map, &i, &locklesslevelsearch);
} }
} }
else else
{ {
unsignedportion = (cupgrid.previewanim % ustep);
x = (unsignedportion * FRACUNIT) + rendertimefrac_unpaused;
x = -(x % fracstep);
while (x < BASEVIDWIDTH * FRACUNIT) while (x < BASEVIDWIDTH * FRACUNIT)
{ {
V_DrawFixedPatch(x + FRACUNIT, (y+2) * FRACUNIT, FRACUNIT, 0, staticpat, NULL); V_DrawFixedPatch(x + FRACUNIT, (y+2) * FRACUNIT, FRACUNIT, 0, staticpat, NULL);
x += step; x += fracstep;
} }
} }
} }
@ -3817,15 +3829,20 @@ static void M_MPOptDrawer(menu_t *m, INT16 extend[3][3])
} }
// Draws the EGGA CHANNEL background. // Draws the EGGA CHANNEL background.
void M_DrawEggaChannel(void) void M_DrawEggaChannelAlignable(boolean centered)
{ {
patch_t *background = W_CachePatchName("M_EGGACH", PU_CACHE); patch_t *background = W_CachePatchName("M_EGGACH", PU_CACHE);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 25); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 25);
V_DrawFixedPatch((menuactive ? 75 : 160)<<FRACBITS, 104<<FRACBITS, FRACUNIT, 0, background, NULL); V_DrawFixedPatch((!centered ? 75 : 160)<<FRACBITS, 104<<FRACBITS, FRACUNIT, 0, background, NULL);
V_DrawVhsEffect(false); // VHS the background! (...sorry OGL my love) V_DrawVhsEffect(false); // VHS the background! (...sorry OGL my love)
} }
void M_DrawEggaChannel(void)
{
M_DrawEggaChannelAlignable(false);
}
// Multiplayer mode option select // Multiplayer mode option select
void M_DrawMPOptSelect(void) void M_DrawMPOptSelect(void)
{ {
@ -4134,7 +4151,7 @@ static void M_DrawServerCountAndHorizontalBar(void)
if (throbindex == UINT8_MAX) if (throbindex == UINT8_MAX)
{ {
V_DrawRightAlignedString( V_DrawRightAlignedMenuString(
BASEVIDWIDTH - currentMenu->x, BASEVIDWIDTH - currentMenu->x,
y, y,
highlightflags, highlightflags,
@ -4143,7 +4160,7 @@ static void M_DrawServerCountAndHorizontalBar(void)
} }
else else
{ {
V_DrawRightAlignedString( V_DrawRightAlignedMenuString(
BASEVIDWIDTH - currentMenu->x - 12, y, BASEVIDWIDTH - currentMenu->x - 12, y,
highlightflags, highlightflags,
text text
@ -4169,11 +4186,15 @@ void M_DrawMPServerBrowser(void)
patch_t *text1 = W_CachePatchName("MENUBGT1", PU_CACHE); patch_t *text1 = W_CachePatchName("MENUBGT1", PU_CACHE);
patch_t *text2 = W_CachePatchName("MENUBGT2", PU_CACHE); patch_t *text2 = W_CachePatchName("MENUBGT2", PU_CACHE);
patch_t *raceh = W_CachePatchName("M_SERV1", PU_CACHE); UINT8 i;
patch_t *batlh = W_CachePatchName("M_SERV2", PU_CACHE);
patch_t *racehs = W_CachePatchName("M_SERV12", PU_CACHE); patch_t *servpats[3];
patch_t *batlhs = W_CachePatchName("M_SERV22", PU_CACHE); patch_t *gearpats[3];
for (i = 0; i < 3; i++)
{
servpats[i] = W_CachePatchName(va("M_SERV%c", i + '1'), PU_CACHE);
gearpats[i] = W_CachePatchName(va("M_SGEAR%c", i + '1'), PU_CACHE);
}
fixed_t text1loop = SHORT(text1->height)*FRACUNIT; fixed_t text1loop = SHORT(text1->height)*FRACUNIT;
fixed_t text2loop = SHORT(text2->width)*FRACUNIT; fixed_t text2loop = SHORT(text2->width)*FRACUNIT;
@ -4182,7 +4203,6 @@ void M_DrawMPServerBrowser(void)
const UINT8 basey = 56; const UINT8 basey = 56;
const INT32 starty = basey - 18*mpmenu.scrolln + mpmenu.slide; const INT32 starty = basey - 18*mpmenu.scrolln + mpmenu.slide;
INT32 ypos = 0; INT32 ypos = 0;
UINT8 i;
// background stuff // background stuff
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName(header[mode][1], PU_CACHE), NULL); V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName(header[mode][1], PU_CACHE), NULL);
@ -4204,8 +4224,6 @@ void M_DrawMPServerBrowser(void)
// the actual server list. // the actual server list.
for (i = 0; i < serverlistcount; i++) for (i = 0; i < serverlistcount; i++)
{ {
boolean racegt = strcmp(serverlist[i].info.gametypename, "Race") == 0;
INT32 transflag = 0; INT32 transflag = 0;
INT32 basetransflag = 0; INT32 basetransflag = 0;
@ -4225,13 +4243,23 @@ void M_DrawMPServerBrowser(void)
{ {
transflag = transflag << V_ALPHASHIFT; // shift the translucency flag. transflag = transflag << V_ALPHASHIFT; // shift the translucency flag.
if (serverlist[i].cachedgtcalc < 3)
{
patch_t *focus;
if (itemOn == 2 && mpmenu.servernum == i) if (itemOn == 2 && mpmenu.servernum == i)
V_DrawFixedPatch(startx*FRACUNIT, (starty + ypos)*FRACUNIT, FRACUNIT, transflag, racegt ? racehs : batlhs, NULL); {
focus = W_CachePatchName(va("M_SERH%c", serverlist[i].cachedgtcalc + '1'), PU_CACHE);
}
else else
V_DrawFixedPatch(startx*FRACUNIT, (starty + ypos)*FRACUNIT, FRACUNIT, transflag, racegt ? raceh : batlh, NULL); {
focus = servpats[serverlist[i].cachedgtcalc];
}
V_DrawFixedPatch(startx*FRACUNIT, (starty + ypos)*FRACUNIT, FRACUNIT, transflag, focus, NULL);
}
// Server name: // Server name:
V_DrawString(startx+11, starty + ypos + 6, transflag, serverlist[i].info.servername); V_DrawThinString(startx+11, starty + ypos + 6, transflag, serverlist[i].info.servername);
// Ping: // Ping:
V_DrawThinString(startx + 191, starty + ypos + 7, transflag, va("%03d", serverlist[i].info.time)); V_DrawThinString(startx + 191, starty + ypos + 7, transflag, va("%03d", serverlist[i].info.time));
@ -4239,16 +4267,34 @@ void M_DrawMPServerBrowser(void)
// Playercount // Playercount
V_DrawThinString(startx + 214, starty + ypos + 7, transflag, va("%02d/%02d", serverlist[i].info.numberofplayer, serverlist[i].info.maxplayer)); V_DrawThinString(startx + 214, starty + ypos + 7, transflag, va("%02d/%02d", serverlist[i].info.numberofplayer, serverlist[i].info.maxplayer));
const char *pwrtext;
if (serverlist[i].cachedgtcalc == GTCALC_CUSTOM)
{
// Show custom gametype name
// (custom PWR is not available, and this is the best place to show the name)
pwrtext = serverlist[i].info.gametypename;
}
else if (serverlist[i].info.avgpwrlv != -1)
{
// Power Level // Power Level
V_DrawThinString(startx + 248, starty + ypos, transflag, va("%04d PLv", serverlist[i].info.avgpwrlv)); pwrtext = va("%04d Pwr", serverlist[i].info.avgpwrlv);
}
else
{
// Fallback
pwrtext = "No Pwr";
}
V_DrawRightAlignedThinString(startx + 276, starty + ypos, transflag, pwrtext);
// game speed if applicable: // game speed if applicable:
if (racegt) if (serverlist[i].cachedgtcalc != GTCALC_BATTLE)
{ {
UINT8 speed = serverlist[i].info.kartvars & SV_SPEEDMASK; UINT8 speed = serverlist[i].info.kartvars & SV_SPEEDMASK;
patch_t *pp = W_CachePatchName(va("M_SDIFF%d", speed), PU_CACHE);
V_DrawFixedPatch((startx + 251)*FRACUNIT, (starty + ypos + 9)*FRACUNIT, FRACUNIT, transflag, pp, NULL); if (speed < 3)
{
V_DrawFixedPatch((startx + 251)*FRACUNIT, (starty + ypos + 9)*FRACUNIT, FRACUNIT, transflag, gearpats[speed], NULL);
}
} }
} }
ypos += SERVERSPACE; ypos += SERVERSPACE;
@ -4274,11 +4320,18 @@ void M_DrawMPServerBrowser(void)
// Draws the cogs and also the options background! // Draws the cogs and also the options background!
void M_DrawOptionsCogs(void) void M_DrawOptionsCogs(void)
{ {
boolean trulystarted = M_GameTrulyStarted(); boolean eggahack = (
currentMenu->prevMenu == &PLAY_MP_HostDef
|| (
currentMenu->prevMenu
&& currentMenu->prevMenu->prevMenu == &PLAY_MP_HostDef
)
);
boolean solidbg = M_GameTrulyStarted() && !eggahack;
UINT32 tick = ((optionsmenu.ticker/10) % 3) + 1; UINT32 tick = ((optionsmenu.ticker/10) % 3) + 1;
// the background isn't drawn outside of being in the main menu state. // the background isn't drawn outside of being in the main menu state.
if (gamestate == GS_MENU && trulystarted) if (gamestate == GS_MENU && solidbg)
{ {
patch_t *back = W_CachePatchName(va("OPT_BG%u", tick), PU_CACHE); patch_t *back = W_CachePatchName(va("OPT_BG%u", tick), PU_CACHE);
INT32 tflag = 0; INT32 tflag = 0;
@ -4299,10 +4352,15 @@ void M_DrawOptionsCogs(void)
} }
else else
{ {
if (eggahack)
{
M_DrawEggaChannelAlignable(true);
}
patch_t *back_pause = W_CachePatchName(va("OPT_BAK%u", tick), PU_CACHE); patch_t *back_pause = W_CachePatchName(va("OPT_BAK%u", tick), PU_CACHE);
V_DrawFixedPatch(0, 0, FRACUNIT, V_MODULATE, back_pause, NULL); V_DrawFixedPatch(0, 0, FRACUNIT, V_MODULATE, back_pause, NULL);
if (!trulystarted) if (!solidbg)
{ {
V_DrawFixedPatch(0, 0, FRACUNIT, (V_ADD|V_70TRANS), back_pause, NULL); V_DrawFixedPatch(0, 0, FRACUNIT, (V_ADD|V_70TRANS), back_pause, NULL);
} }

View file

@ -605,7 +605,8 @@ menu_t *M_SpecificMenuRestore(menu_t *torestore)
if (torestore == &PLAY_CupSelectDef if (torestore == &PLAY_CupSelectDef
|| torestore == &PLAY_LevelSelectDef || torestore == &PLAY_LevelSelectDef
|| torestore == &PLAY_TimeAttackDef) || torestore == &PLAY_TimeAttackDef
|| torestore == &PLAY_TAReplayDef)
{ {
// Handle unlock restrictions // Handle unlock restrictions

View file

@ -5,6 +5,7 @@
#include "../k_menu.h" #include "../k_menu.h"
#include "../k_grandprix.h" // K_CanChangeRules #include "../k_grandprix.h" // K_CanChangeRules
#include "../m_cond.h" // Condition Sets #include "../m_cond.h" // Condition Sets
#include "../k_follower.h"
#include "../s_sound.h" #include "../s_sound.h"
// options menu -- see mopt_e // options menu -- see mopt_e
@ -96,6 +97,7 @@ void M_InitOptions(INT32 choice)
(M_SecretUnlocked(SECRET_ENCORE, false) ? (IT_STRING | IT_CVAR) : IT_DISABLED); (M_SecretUnlocked(SECRET_ENCORE, false) ? (IT_STRING | IT_CVAR) : IT_DISABLED);
} }
// Data Options
OPTIONS_DataAdvancedDef.menuitems[daopt_addon].status = (M_SecretUnlocked(SECRET_ADDONS, true) OPTIONS_DataAdvancedDef.menuitems[daopt_addon].status = (M_SecretUnlocked(SECRET_ADDONS, true)
? (IT_STRING | IT_SUBMENU) ? (IT_STRING | IT_SUBMENU)
: (IT_NOTHING | IT_SPACE)); : (IT_NOTHING | IT_SPACE));
@ -211,6 +213,7 @@ void M_OptionsTick(void)
static void M_OptionsMenuGoto(menu_t *assignment) static void M_OptionsMenuGoto(menu_t *assignment)
{ {
assignment->prevMenu = currentMenu; assignment->prevMenu = currentMenu;
assignment->music = currentMenu->music;
M_SetupNextMenu(assignment, false); M_SetupNextMenu(assignment, false);
if (currentMenu != &OPTIONS_MainDef) if (currentMenu != &OPTIONS_MainDef)
{ {
@ -236,6 +239,7 @@ void M_SoundOptions(INT32 choice)
void M_GameplayOptions(INT32 choice) void M_GameplayOptions(INT32 choice)
{ {
(void)choice; (void)choice;
OPTIONS_GameplayItemsDef.music = currentMenu->music;
M_OptionsMenuGoto(&OPTIONS_GameplayDef); M_OptionsMenuGoto(&OPTIONS_GameplayDef);
OPTIONS_MainDef.lastOn = mopt_gameplay; OPTIONS_MainDef.lastOn = mopt_gameplay;
} }
@ -243,6 +247,7 @@ void M_GameplayOptions(INT32 choice)
void M_ServerOptions(INT32 choice) void M_ServerOptions(INT32 choice)
{ {
(void)choice; (void)choice;
OPTIONS_ServerAdvancedDef.music = currentMenu->music;
M_OptionsMenuGoto(&OPTIONS_ServerDef); M_OptionsMenuGoto(&OPTIONS_ServerDef);
OPTIONS_MainDef.lastOn = mopt_server; OPTIONS_MainDef.lastOn = mopt_server;
} }

View file

@ -210,8 +210,29 @@ void tick_routine(void)
void init_routine(void) void init_routine(void)
{ {
OPTIONS_Sound[sopt_followhorns].status = IT_SECRET;
OPTIONS_Sound[sopt_attackmusic].status = IT_SECRET; OPTIONS_Sound[sopt_attackmusic].status = IT_SECRET;
// We show a kindness. If you have online available,
// even if you haven't found a single Follower, you
// should be able to turn off other people's horns.
bool allow = M_SecretUnlocked(SECRET_ONLINE, true);
if (!allow)
{
UINT16 j;
for (j = 0; j < numfollowers; j++)
{
if (!K_FollowerUsable(j))
continue;
allow = true;
break;
}
}
if (allow)
OPTIONS_Sound[sopt_followhorns].status = IT_STRING | IT_CVAR;
if (M_SecretUnlocked(SECRET_TIMEATTACK, true) || if (M_SecretUnlocked(SECRET_TIMEATTACK, true) ||
M_SecretUnlocked(SECRET_PRISONBREAK, true) || M_SecretUnlocked(SECRET_PRISONBREAK, true) ||
M_SecretUnlocked(SECRET_SPECIALATTACK, true)) M_SecretUnlocked(SECRET_SPECIALATTACK, true))
@ -252,16 +273,22 @@ menuitem_t OPTIONS_Sound[] =
{IT_SPACE | IT_NOTHING, NULL, NULL, {IT_SPACE | IT_NOTHING, NULL, NULL,
NULL, {NULL}, 0, 0}, NULL, {NULL}, 0, 0},
{IT_HEADER, "Preferences...", NULL,
NULL, {NULL}, 0, 0},
{IT_STRING | IT_CVAR, "Chat Notifications", "Play a sound effect when chat messages appear.", {IT_STRING | IT_CVAR, "Chat Notifications", "Play a sound effect when chat messages appear.",
NULL, {.cvar = &cv_chatnotifications}, 0, 0}, NULL, {.cvar = &cv_chatnotifications}, 0, 0},
{IT_STRING | IT_CVAR, "Character Voices", "How often to play character voices in a race.", {IT_STRING | IT_CVAR, "Character Voices", "How often to play character voices in a round.",
NULL, {.cvar = &cv_kartvoices}, 0, 0}, NULL, {.cvar = &cv_kartvoices}, 0, 0},
{IT_STRING | IT_CVAR, "Follower Horns", "How often to play follower horns in a round.",
NULL, {.cvar = &cv_karthorns}, 0, 0},
{IT_STRING | IT_CVAR, "Continuous Attack Music", "Keep music playing seamlessly when retrying in Attack modes.", {IT_STRING | IT_CVAR, "Continuous Attack Music", "Keep music playing seamlessly when retrying in Attack modes.",
NULL, {.cvar = &cv_continuousmusic}, 0, 0}, NULL, {.cvar = &cv_continuousmusic}, 0, 0},
{IT_SPACE | IT_NOTHING, NULL, NULL, {IT_SPACE | IT_DYBIGSPACE, NULL, NULL,
NULL, {NULL}, 0, 0}, NULL, {NULL}, 0, 0},
{IT_HEADER, "Advanced...", NULL, {IT_HEADER, "Advanced...", NULL,

View file

@ -40,7 +40,7 @@ menuitem_t PLAY_RaceDifficulty[] =
{IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", "MENUI004", {.routine = M_LevelSelectInit}, 2, GT_RACE}, {IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", "MENUI004", {.routine = M_LevelSelectInit}, 2, GT_RACE},
// Match Race // Match Race
{IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", "MENUI005", {.routine = M_LevelSelectInit}, 0, GT_RACE}, {IT_STRING | IT_CALL, "Map Select", "Go on and select a course!", "MENUI005", {.routine = M_LevelSelectInit}, 0, GT_RACE},
{IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0},
}; };

View file

@ -337,7 +337,18 @@ void CV_SPBAttackChanged(void)
{ {
extern CV_PossibleValue_t dummystaff_cons_t[]; extern CV_PossibleValue_t dummystaff_cons_t[];
dummystaff_cons_t[1].value = mapheaderinfo[levellist.choosemap]->ghostCount-1; dummystaff_cons_t[1].value = mapheaderinfo[levellist.choosemap]->ghostCount-1;
CV_SetValue(&cv_dummystaff, 0);
// LAST MINUTE SANITY
static UINT16 laststaffmap = NEXTMAP_INVALID;
if (laststaffmap != levellist.choosemap || cv_dummystaff.value < dummystaff_cons_t[0].value)
{
laststaffmap = levellist.choosemap;
CV_SetValue(&cv_dummystaff, dummystaff_cons_t[0].value);
}
else if (cv_dummystaff.value > dummystaff_cons_t[1].value)
{
CV_SetValue(&cv_dummystaff, dummystaff_cons_t[1].value);
}
PLAY_TAReplay[tareplay_staff].status = IT_STRING|IT_ARROWS; PLAY_TAReplay[tareplay_staff].status = IT_STRING|IT_ARROWS;
PLAY_TAGhosts[taghost_staff].status = IT_STRING|IT_CVAR; PLAY_TAGhosts[taghost_staff].status = IT_STRING|IT_CVAR;
@ -416,7 +427,7 @@ void M_HandleStaffReplay(INT32 choice)
{ {
mapheader_t *mapheader; mapheader_t *mapheader;
staffbrief_t *staffbrief; staffbrief_t *staffbrief;
restoreMenu = &PLAY_TimeAttackDef; restoreMenu = &PLAY_TAReplayDef;
M_ClearMenus(true); M_ClearMenus(true);
demo.loadfiles = false; demo.loadfiles = false;
@ -473,7 +484,7 @@ void M_ReplayTimeAttack(INT32 choice)
return; return;
} }
restoreMenu = &PLAY_TimeAttackDef; restoreMenu = &PLAY_TAReplayDef;
M_ClearMenus(true); M_ClearMenus(true);
demo.loadfiles = false; demo.loadfiles = false;

View file

@ -244,6 +244,12 @@ void M_MPOptSelectInit(INT32 choice)
M_PrevMenuGametype(forbidden); M_PrevMenuGametype(forbidden);
M_NextMenuGametype(forbidden); M_NextMenuGametype(forbidden);
if (cv_advertise.value)
{
// Try to have the rules available "early" for opening the Host Game menu.
Get_rules();
}
if (choice != -1) if (choice != -1)
{ {
M_SetupNextMenu(&PLAY_MP_OptSelectDef, false); M_SetupNextMenu(&PLAY_MP_OptSelectDef, false);

View file

@ -5,10 +5,41 @@
#include "../s_sound.h" #include "../s_sound.h"
#include "../z_zone.h" #include "../z_zone.h"
#include "../mserv.h" #include "../mserv.h"
#include "../v_video.h"
#include "../m_easing.h"
static void draw_routine(void) static void draw_routine(void)
{ {
M_DrawRaceDifficulty(); M_DrawRaceDifficulty();
INT32 tx = M_EaseWithTransition(Easing_Linear, 5 * 48);
if (gametypes[menugametype]->rules & GTR_CIRCUIT) // TODO: speed == KARTSPEED_AUTO
{
V_DrawRightAlignedThinString(
294 + tx,
84,
highlightflags,
va("(%s)", cv_kartspeed.string)
);
}
else
{
V_DrawRightAlignedThinString(
294 + tx,
84,
highlightflags,
"(Time/Points)"
);
}
V_DrawRightAlignedThinString(
294 + tx,
98,
!CV_IsSetToDefault(&cv_advertise) ? warningflags : highlightflags,
va("(Advertise: %s)", cv_advertise.string)
);
M_DrawMasterServerReminder(); M_DrawMasterServerReminder();
} }
@ -47,7 +78,7 @@ menuitem_t PLAY_MP_Host[] =
{IT_STRING2 | IT_CALL, "Server Options...", "Update server settings.", {IT_STRING2 | IT_CALL, "Server Options...", "Update server settings.",
NULL, {.routine = M_ServerOptions}, 0, 0}, NULL, {.routine = M_ServerOptions}, 0, 0},
{IT_STRING | IT_CALL, "Map Select", "Go on and select a level!", {IT_STRING | IT_CALL, "Map Select", "Go on and select a course!",
NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0}, NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0},
{IT_STRING | IT_CALL, "Back", NULL, {IT_STRING | IT_CALL, "Back", NULL,
@ -75,7 +106,7 @@ menu_t PLAY_MP_HostDef = {
void M_PopupMasterServerRules(void) void M_PopupMasterServerRules(void)
{ {
#ifdef MASTERSERVER #ifdef MASTERSERVER
if (cv_advertise.value && (serverrunning || currentMenu == &PLAY_MP_HostDef)) if (cv_advertise.value && (serverrunning || gamestate == GS_MENU))
{ {
char *rules = GetMasterServerRules(); char *rules = GetMasterServerRules();
@ -96,17 +127,14 @@ void M_MPHostInit(INT32 choice)
M_SetupNextMenu(&PLAY_MP_HostDef, false); M_SetupNextMenu(&PLAY_MP_HostDef, false);
Get_rules(); Get_rules();
// There's one downside to doing it this way: // As an async request, rules won't necessarily
// if you turn advertise on via the console, // be ready in time for the following call...
// then access this menu for the first time,
// no rules will pop up because they haven't
// arrived yet.
M_PopupMasterServerRules(); M_PopupMasterServerRules();
// HOWEVER, this menu popup isn't for people // ... but either cv_advertise is off, in case
// who know how to use the Developer Console. // it'll be ready for OPTIONS_ServerDef, or it's
// People who CAN do that should already know // been turned on via console/elsewhere and
// what kind of service they're connecting to. // Get_rules() has already been called by
// (it'll still appear in the logs later, too!) // M_MPOptSelectInit.
} }
void M_HandleHostMenuGametype(INT32 choice) void M_HandleHostMenuGametype(INT32 choice)

View file

@ -299,7 +299,28 @@ void M_ServerListFillDebug(void)
strcpy(serverlist[i].info.servername, va("Serv %d", i+1)); strcpy(serverlist[i].info.servername, va("Serv %d", i+1));
strcpy(serverlist[i].info.gametypename, i & 1 ? "Race" : "Battle"); const char *tempgtname;
if (i < 10 && mpmenu.room == 1)
{
tempgtname = va("%c%c%c%c",
'A' + M_RandomKey(26),
'a' + M_RandomKey(26),
'a' + M_RandomKey(26),
'a' + M_RandomKey(26)
);
}
else
tempgtname = (i & 1) ? "Race" : "Battle";
strcpy(serverlist[i].info.gametypename, tempgtname);
const INT32 gtidentifier = G_GetGametypeByName(tempgtname);
UINT8 gtcalc = GTCALC_RACE;
if (gtidentifier != GT_RACE)
{
gtcalc = (gtidentifier == GT_BATTLE) ? GTCALC_BATTLE : GTCALC_CUSTOM;
}
serverlist[i].cachedgtcalc = gtcalc;
serverlist[i].info.kartvars = M_RandomRange(0, 3) & SV_SPEEDMASK; serverlist[i].info.kartvars = M_RandomRange(0, 3) & SV_SPEEDMASK;

View file

@ -751,7 +751,7 @@ void M_LevelSelected(INT16 add, boolean menuupdate)
CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string); CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string);
CV_StealthSet(&cv_kartencore, (cv_dummygpencore.value == 1) ? "On" : "Auto"); CV_StealthSet(&cv_kartencore, (cv_dummygpencore.value == 1) ? "On" : "Auto");
CV_StealthSet(&cv_kartspeed, (cv_dummykartspeed.value == KARTSPEED_NORMAL) ? "Auto" : cv_dummykartspeed.string); CV_StealthSet(&cv_kartspeed, (cv_dummykartspeed.value == KARTSPEED_NORMAL) ? "Auto Gear" : cv_dummykartspeed.string);
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);