diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 53bbaf0b6..0c8d736de 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -163,6 +163,7 @@ static UINT8 localtextcmd[MAXSPLITSCREENPLAYERS][MAXTEXTCMD]; static tic_t neededtic; SINT8 servernode = 0; // the number of the server node char connectedservername[MAXSERVERNAME]; +char connectedservercontact[MAXSERVERCONTACT]; /// \brief do we accept new players? /// \todo WORK! boolean acceptnewnode = true; @@ -1283,6 +1284,9 @@ static boolean SV_SendServerConfig(INT32 node) memcpy(netbuffer->u.servercfg.server_context, server_context, 8); + strncpy(netbuffer->u.servercfg.server_name, cv_servername.string, MAXSERVERNAME); + strncpy(netbuffer->u.servercfg.server_contact, cv_server_contact.string, MAXSERVERCONTACT); + { const size_t len = sizeof (serverconfig_pak); @@ -3799,6 +3803,9 @@ void SV_ResetServer(void) // clear server_context memset(server_context, '-', 8); + strncpy(connectedservername, "\0", MAXSERVERNAME); + strncpy(connectedservercontact, "\0", MAXSERVERCONTACT); + CV_RevertNetVars(); // Copy our unlocks to a place where net material can grab at/overwrite them safely. @@ -3811,9 +3818,10 @@ void SV_ResetServer(void) DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } -static inline void SV_GenContext(void) +static void SV_GenContext(void) { UINT8 i; + // generate server_context, as exactly 8 bytes of randomly mixed A-Z and a-z // (hopefully M_Random is initialized!! if not this will be awfully silly!) for (i = 0; i < 8; i++) @@ -3824,6 +3832,9 @@ static inline void SV_GenContext(void) else // lowercase server_context[i] = 'a'+(a-26); } + + strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); + strncpy(connectedservercontact, cv_server_contact.string, MAXSERVERCONTACT); } // @@ -4874,7 +4885,11 @@ static void HandlePacketFromAwayNode(SINT8 node) G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; + memcpy(server_context, netbuffer->u.servercfg.server_context, 8); + + strncpy(connectedservername, netbuffer->u.servercfg.server_name, MAXSERVERNAME); + strncpy(connectedservercontact, netbuffer->u.servercfg.server_contact, MAXSERVERCONTACT); } #ifdef HAVE_DISCORDRPC diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e2dd85bff..fdcf4d0fe 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -43,6 +43,9 @@ applications may follow different packet versions. #define HU_MAXMSGLEN 223 +#define MAXSERVERNAME 32 +#define MAXSERVERCONTACT 1024 + // Networking and tick handling related. #define BACKUPTICS 512 // more than enough for most timeouts.... #define CLIENTBACKUPTICS 32 @@ -226,6 +229,9 @@ struct serverconfig_pak UINT8 maxplayer; boolean allownewplayer; boolean discordinvites; + + char server_name[MAXSERVERNAME]; + char server_contact[MAXSERVERCONTACT]; } ATTRPACK; struct filetx_pak @@ -276,7 +282,6 @@ struct clientconfig_pak #define SV_DEDICATED 0x40 // server is dedicated #define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil -#define MAXSERVERNAME 32 #define MAXFILENEEDED 915 #define MAX_MIRROR_LENGTH 256 // This packet is too large @@ -509,6 +514,7 @@ extern UINT16 software_MAXPACKETLENGTH; extern boolean acceptnewnode; extern SINT8 servernode; extern char connectedservername[MAXSERVERNAME]; +extern char connectedservercontact[MAXSERVERCONTACT]; extern UINT32 ourIP; extern uint8_t lastReceivedKey[MAXNETNODES][MAXSPLITSCREENPLAYERS][PUBKEYLENGTH]; extern uint8_t lastSentChallenge[MAXNETNODES][CHALLENGELENGTH]; diff --git a/src/d_main.c b/src/d_main.c index 432a20e72..0d80071dc 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1916,8 +1916,6 @@ void D_SRB2Main(void) COM_BufExecute(); // ensure the command buffer gets executed before the map starts (+skin) - strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); - if (M_CheckParm("-gametype") && M_IsNextParm()) { // from Command_Map_f diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7ad288f25..6193dca52 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -244,8 +244,6 @@ static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}}; -static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}}; - static CV_PossibleValue_t sleeping_cons_t[] = {{0, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}}; static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}}; @@ -267,11 +265,6 @@ consvar_t cv_duelspectatorreentry = CVAR_INIT ("duelspectatorreentry", "180", CV static CV_PossibleValue_t antigrief_cons_t[] = {{10, "MIN"}, {180, "MAX"}, {0, "Off"}, {0, NULL}}; consvar_t cv_antigrief = CVAR_INIT ("antigrief", "30", CV_NETVAR, antigrief_cons_t, NULL); -consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, startingliveslimit_cons_t, NULL); - -static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "1", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL); - consvar_t cv_seenames = CVAR_INIT ("seenames", "On", CV_SAVE, CV_OnOff, NULL); // names @@ -753,10 +746,6 @@ void D_RegisterServerCommands(void) // for master server connection AddMServCommands(); - // p_mobj.c - CV_RegisterVar(&cv_itemrespawntime); - CV_RegisterVar(&cv_itemrespawn); - // misc CV_RegisterVar(&cv_pointlimit); CV_RegisterVar(&cv_numlaps); @@ -774,7 +763,6 @@ void D_RegisterServerCommands(void) K_RegisterKartStuff(); // SRB2kart - CV_RegisterVar(&cv_startinglives); CV_RegisterVar(&cv_countdowntime); CV_RegisterVar(&cv_overtime); CV_RegisterVar(&cv_pause); @@ -789,7 +777,6 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_spectatorreentry); CV_RegisterVar(&cv_duelspectatorreentry); CV_RegisterVar(&cv_antigrief); - CV_RegisterVar(&cv_respawntime); // d_clisrv CV_RegisterVar(&cv_maxconnections); @@ -1038,6 +1025,7 @@ void D_RegisterClientCommands(void) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { CV_RegisterVar(&cv_kickstartaccel[i]); + CV_RegisterVar(&cv_autoroulette[i]); CV_RegisterVar(&cv_shrinkme[i]); CV_RegisterVar(&cv_deadzone[i]); CV_RegisterVar(&cv_rumble[i]); @@ -1783,6 +1771,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) enum { WP_KICKSTARTACCEL = 1<<0, WP_SHRINKME = 1<<1, + WP_AUTOROULETTE = 1<<2, }; void WeaponPref_Send(UINT8 ssplayer) @@ -1792,6 +1781,9 @@ void WeaponPref_Send(UINT8 ssplayer) if (cv_kickstartaccel[ssplayer].value) prefs |= WP_KICKSTARTACCEL; + if (cv_autoroulette[ssplayer].value) + prefs |= WP_AUTOROULETTE; + if (cv_shrinkme[ssplayer].value) prefs |= WP_SHRINKME; @@ -1807,6 +1799,9 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum) if (player->pflags & PF_KICKSTARTACCEL) prefs |= WP_KICKSTARTACCEL; + if (player->pflags & PF_AUTOROULETTE) + prefs |= WP_AUTOROULETTE; + if (player->pflags & PF_SHRINKME) prefs |= WP_SHRINKME; @@ -1819,11 +1814,14 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum) UINT8 prefs = READUINT8(*cp); - player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME); + player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_AUTOROULETTE); if (prefs & WP_KICKSTARTACCEL) player->pflags |= PF_KICKSTARTACCEL; + if (prefs & WP_AUTOROULETTE) + player->pflags |= PF_AUTOROULETTE; + if (prefs & WP_SHRINKME) player->pflags |= PF_SHRINKME; @@ -3012,8 +3010,6 @@ static void Command_Map_f(void) multiplayer = true; netgame = false; - strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); - if (cv_maxconnections.value < ssplayers+1) CV_SetValue(&cv_maxconnections, ssplayers+1); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index acf6b8336..ebd24b266 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -49,10 +49,6 @@ extern consvar_t cv_seenames; extern consvar_t cv_usemouse; extern consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS]; -// normally in p_mobj but the .h is not read -extern consvar_t cv_itemrespawntime; -extern consvar_t cv_itemrespawn; - extern consvar_t cv_pointlimit; extern consvar_t cv_timelimit; extern consvar_t cv_numlaps; @@ -70,7 +66,7 @@ extern consvar_t cv_countdowntime; extern consvar_t cv_mute; extern consvar_t cv_pause; -extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_maxplayers, cv_respawntime; +extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_maxplayers; extern consvar_t cv_spectatorreentry, cv_duelspectatorreentry, cv_antigrief; // SRB2kart items @@ -113,7 +109,6 @@ extern consvar_t cv_alttitle, cv_itemfinder; extern consvar_t cv_inttime, cv_advancemap; extern consvar_t cv_overtime; -extern consvar_t cv_startinglives; // for F_finale.c extern consvar_t cv_rollingdemos; diff --git a/src/d_player.h b/src/d_player.h index 6d6e887d1..292ec12f4 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -64,7 +64,9 @@ typedef enum { PF_GODMODE = 1<<0, // Immortal. No lightsnake from pits either - // free: 1<<1 and 1<<2 + // free: 1<<1 + + PF_AUTOROULETTE = 1<<2, // Accessibility: Non-deterministic item box, no manual stop. // Look back VFX has been spawned // TODO: Is there a better way to track this? @@ -437,6 +439,7 @@ struct itemroulette_t boolean eggman; boolean ringbox; + boolean autoroulette; }; // enum for bot item priorities diff --git a/src/deh_tables.c b/src/deh_tables.c index 8e7506af3..e51e2e878 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5914,7 +5914,7 @@ const char *const PLAYERFLAG_LIST[] = { // free: 1<<1 and 1<<2 (name un-matchable) "\x01", - "\x01", + "AUTOROULETTE", // Item box accessibility // Look back VFX has been spawned // TODO: Is there a better way to track this? diff --git a/src/g_demo.c b/src/g_demo.c index 6708cfd84..5bcee7d48 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -133,10 +133,11 @@ demoghost *ghosts = NULL; #define DF_ENCORE 0x40 #define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode! -#define DEMO_SPECTATOR 0x01 -#define DEMO_KICKSTART 0x02 -#define DEMO_SHRINKME 0x04 -#define DEMO_BOT 0x08 +#define DEMO_SPECTATOR 0x01 +#define DEMO_KICKSTART 0x02 +#define DEMO_SHRINKME 0x04 +#define DEMO_BOT 0x08 +#define DEMO_AUTOROULETTE 0x10 // For demos #define ZT_FWD 0x0001 @@ -2474,6 +2475,8 @@ void G_BeginRecording(void) i |= DEMO_SPECTATOR; if (player->pflags & PF_KICKSTARTACCEL) i |= DEMO_KICKSTART; + if (player->pflags & PF_AUTOROULETTE) + i |= DEMO_AUTOROULETTE; if (player->pflags & PF_SHRINKME) i |= DEMO_SHRINKME; if (player->bot == true) @@ -3436,6 +3439,11 @@ void G_DoPlayDemo(const char *defdemoname) else players[p].pflags &= ~PF_KICKSTARTACCEL; + if (flags & DEMO_AUTOROULETTE) + players[p].pflags |= PF_AUTOROULETTE; + else + players[p].pflags &= ~PF_AUTOROULETTE; + if (flags & DEMO_SHRINKME) players[p].pflags |= PF_SHRINKME; else diff --git a/src/g_game.c b/src/g_game.c index e26f13a48..1ef8faee1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -405,6 +405,13 @@ consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS] = { CVAR_INIT ("kickstartaccel4", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange4) }; +consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("autoroulette", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange), + CVAR_INIT ("autoroulette2", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange2), + CVAR_INIT ("autoroulette3", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange3), + CVAR_INIT ("autoroulette4", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange4) +}; + consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS] = { CVAR_INIT ("shrinkme", "Off", CV_CALL, CV_OnOff, weaponPrefChange), CVAR_INIT ("shrinkme2", "Off", CV_CALL, CV_OnOff, weaponPrefChange2), @@ -2212,7 +2219,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) totalring = players[player].totalring; xtralife = players[player].xtralife; - pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE)); + pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_AUTOROULETTE)); // SRB2kart memcpy(&itemRoulette, &players[player].itemRoulette, sizeof (itemRoulette)); diff --git a/src/g_game.h b/src/g_game.h index e781f17ee..84dc5f4ac 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -95,6 +95,7 @@ extern consvar_t cv_songcredits; extern consvar_t cv_pauseifunfocused; extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS]; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e97d41183..fd9fa3c97 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1952,7 +1952,7 @@ void HU_DrawSongCredits(void) } else { - y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT; + y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 40) * FRACUNIT; } INT32 bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans / 2); diff --git a/src/k_hud.c b/src/k_hud.c index 569304485..af15b474a 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -193,6 +193,8 @@ static patch_t *kp_bossret[4]; static patch_t *kp_trickcool[2]; +patch_t *kp_autoroulette; + patch_t *kp_capsuletarget_arrow[2][2]; patch_t *kp_capsuletarget_icon[2]; patch_t *kp_capsuletarget_far[2]; @@ -710,6 +712,8 @@ void K_LoadKartHUDGraphics(void) HU_UpdatePatch(&kp_trickcool[0], "K_COOL1"); HU_UpdatePatch(&kp_trickcool[1], "K_COOL2"); + HU_UpdatePatch(&kp_autoroulette, "A11YITEM"); + sprintf(buffer, "K_BOSB0x"); for (i = 0; i < 8; i++) { @@ -2743,70 +2747,92 @@ static void K_drawRingCounter(boolean gametypeinfoshown) static void K_drawKartAccessibilityIcons(boolean gametypeinfoshown, INT32 fx) { - INT32 fy = LAPS_Y-14; - INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN; - //INT32 step = 1; -- if there's ever more than one accessibility icon - - fx += LAPS_X; - - if (r_splitscreen < 2) // adjust to speedometer height - { - if (gametypeinfoshown) - { - fy -= 11; - - if ((gametyperules & (GTR_BUMPERS|GTR_CIRCUIT)) == GTR_BUMPERS) - fy -= 4; - } - else - { - fy += 9; - } - } - else - { - fx = LAPS_X+43; - fy = LAPS_Y; - if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]])) // If we are not P1 or P3... - { - splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT); - fx = (BASEVIDWIDTH/2) - (fx + 10); - //step = -step; - } - } - - if (stplyr->pflags & PF_KICKSTARTACCEL) // just KICKSTARTACCEL right now, maybe more later - { - SINT8 col = 0, wid, fil, ofs; - UINT8 i = 7; - ofs = (stplyr->kickstartaccel == ACCEL_KICKSTART) ? 1 : 0; - fil = i-(stplyr->kickstartaccel*i)/ACCEL_KICKSTART; - - V_DrawFill(fx+4, fy+ofs-1, 2, 1, 31|V_SLIDEIN|splitflags); - V_DrawFill(fx, (fy+ofs-1)+8, 10, 1, 31|V_SLIDEIN|splitflags); - - while (i--) - { - wid = (i/2)+1; - V_DrawFill(fx+4-wid, fy+ofs+i, 2+(wid*2), 1, 31|V_SLIDEIN|splitflags); - if (fil > 0) - { - if (i < fil) - col = 23; - else if (i == fil) - col = 3; - else - col = 5 + (i-fil)*2; - } - else if ((leveltime % 7) == i) - col = 0; - else - col = 3; - V_DrawFill(fx+5-wid, fy+ofs+i, (wid*2), 1, col|V_SLIDEIN|splitflags); - } - - //fx += step*12; - } + INT32 fy = LAPS_Y-14; + INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN; + + boolean mirror = false; + + fx += LAPS_X; + + if (r_splitscreen < 2) // adjust to speedometer height + { + if (gametypeinfoshown) + { + fy -= 11; + + if ((gametyperules & (GTR_BUMPERS|GTR_CIRCUIT)) == GTR_BUMPERS) + fy -= 4; + } + else + { + fy += 9; + } + } + else + { + fx = LAPS_X+44; + fy = LAPS_Y; + if (!(stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]])) // If we are not P1 or P3... + { + splitflags ^= (V_SNAPTOLEFT|V_SNAPTORIGHT); + fx = (BASEVIDWIDTH/2) - fx; + mirror = true; + } + } + + // Kickstart Accel + if (stplyr->pflags & PF_KICKSTARTACCEL) + { + if (mirror) + fx -= 10; + + SINT8 col = 0, wid, fil, ofs; + UINT8 i = 7; + ofs = (stplyr->kickstartaccel == ACCEL_KICKSTART) ? 1 : 0; + fil = i-(stplyr->kickstartaccel*i)/ACCEL_KICKSTART; + + V_DrawFill(fx+4, fy+ofs-1, 2, 1, 31|V_SLIDEIN|splitflags); + V_DrawFill(fx, (fy+ofs-1)+8, 10, 1, 31|V_SLIDEIN|splitflags); + + while (i--) + { + wid = (i/2)+1; + V_DrawFill(fx+4-wid, fy+ofs+i, 2+(wid*2), 1, 31|V_SLIDEIN|splitflags); + if (fil > 0) + { + if (i < fil) + col = 23; + else if (i == fil) + col = 3; + else + col = 5 + (i-fil)*2; + } + else if ((leveltime % 7) == i) + col = 0; + else + col = 3; + V_DrawFill(fx+5-wid, fy+ofs+i, (wid*2), 1, col|V_SLIDEIN|splitflags); + } + + if (mirror) + fx--; + else + fx += 10 + 1; + } + + // Auto Roulette + if (stplyr->pflags & PF_AUTOROULETTE) + { + if (mirror) + fx -= 12; + + V_DrawScaledPatch(fx, fy-1, V_SLIDEIN|splitflags, kp_autoroulette); + + if (mirror) + fx--; + else + fx += 12 + 1; + } } static void K_drawKartSpeedometer(boolean gametypeinfoshown) diff --git a/src/k_hud.h b/src/k_hud.h index 041243d5b..d982c851b 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -61,6 +61,8 @@ extern patch_t *kp_capsuletarget_near[8]; extern patch_t *kp_superflickytarget[4]; +extern patch_t *kp_autoroulette; + extern patch_t *kp_button_a[2][2]; extern patch_t *kp_button_b[2][2]; extern patch_t *kp_button_c[2][2]; diff --git a/src/k_menu.h b/src/k_menu.h index 70f6b79c3..69ec29542 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -981,6 +981,7 @@ extern INT16 controlleroffsets[][2]; extern consvar_t cv_dummyprofilename; extern consvar_t cv_dummyprofileplayername; extern consvar_t cv_dummyprofilekickstart; +extern consvar_t cv_dummyprofileautoroulette; extern consvar_t cv_dummyprofilerumble; void M_ResetOptions(void); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 23c989505..800ff3c6c 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -825,6 +825,13 @@ void M_Drawer(void) } } + if (netgame && Playing()) + { + boolean mainpause_open = menuactive && currentMenu == &PAUSE_MainDef; + + ST_DrawServerSplash(!mainpause_open); + } + // focus lost notification goes on top of everything, even the former everything if (window_notinfocus && cv_showfocuslost.value) { diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 8a596b663..54b0f26b7 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -1215,6 +1215,7 @@ void M_Init(void) CV_RegisterVar(&cv_dummyprofilename); CV_RegisterVar(&cv_dummyprofileplayername); CV_RegisterVar(&cv_dummyprofilekickstart); + CV_RegisterVar(&cv_dummyprofileautoroulette); CV_RegisterVar(&cv_dummyprofilerumble); CV_RegisterVar(&cv_dummygpdifficulty); diff --git a/src/k_profiles.c b/src/k_profiles.c index f0a0a8e89..817392d68 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -68,6 +68,7 @@ profile_t* PR_MakeProfile( strcpy(new->follower, fname); new->followercolor = fcol; new->kickstartaccel = false; + new->autoroulette = false; // Copy from gamecontrol directly as we'll be setting controls up directly in the profile. memcpy(new->controls, controlarray, sizeof(new->controls)); @@ -84,6 +85,7 @@ profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const // Player bound cvars: new->kickstartaccel = cv_kickstartaccel[pnum].value; + new->autoroulette = cv_autoroulette[pnum].value; new->rumble = cv_rumble[pnum].value; return new; @@ -270,6 +272,7 @@ void PR_SaveProfiles(void) // Consvars. WRITEUINT8(save.p, profilesList[i]->kickstartaccel); + WRITEUINT8(save.p, profilesList[i]->autoroulette); WRITEUINT8(save.p, profilesList[i]->rumble); // Controls. @@ -407,6 +410,18 @@ void PR_LoadProfiles(void) // Consvars. profilesList[i]->kickstartaccel = (boolean)READUINT8(save.p); + + // 6->7, add autoroulette + if (version < 7) + { + profilesList[i]->autoroulette = false; + + } + else + { + profilesList[i]->autoroulette = (boolean)READUINT8(save.p); + } + if (version < 4) { profilesList[i]->rumble = true; @@ -459,6 +474,7 @@ static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum) { // toggles CV_StealthSetValue(&cv_kickstartaccel[playernum], p->kickstartaccel); + CV_StealthSetValue(&cv_autoroulette[playernum], p->autoroulette); // set controls... memcpy(&gamecontrol[playernum], p->controls, sizeof(gamecontroldefault)); diff --git a/src/k_profiles.h b/src/k_profiles.h index d08c350be..8fc72212f 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -31,7 +31,7 @@ extern "C" { #define SKINNAMESIZE 16 #define PROFILENAMELEN 6 -#define PROFILEVER 6 +#define PROFILEVER 7 #define MAXPROFILES 16 #define PROFILESFILE "ringprofiles.prf" #define PROFILE_GUEST 0 @@ -74,6 +74,7 @@ struct profile_t // Player-specific consvars. // @TODO: List all of those boolean kickstartaccel; // cv_kickstartaccel + boolean autoroulette; // cv_autoroulette boolean rumble; // cv_rumble // Finally, control data itself diff --git a/src/k_roulette.c b/src/k_roulette.c index f54b2c9e4..3dce1b705 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -1074,6 +1074,7 @@ static void K_InitRoulette(itemroulette_t *const roulette) roulette->active = true; roulette->eggman = false; roulette->ringbox = false; + roulette->autoroulette = false; for (i = 0; i < MAXPLAYERS; i++) { @@ -1235,6 +1236,12 @@ static void K_CalculateRouletteSpeed(itemroulette_t *const roulette) return; } + if (roulette->autoroulette == true) + { + roulette->speed = ROULETTE_SPEED_FASTEST; + return; + } + if (K_TimeAttackRules() == true) { // Time Attack rules; use a consistent speed. @@ -1296,6 +1303,10 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet if (player != NULL) { roulette->baseDist = K_UndoMapScaling(player->distancetofinish); + + if (player->pflags & PF_AUTOROULETTE) + roulette->autoroulette = true; + K_CalculateRouletteSpeed(roulette); } @@ -1456,6 +1467,9 @@ void K_StartItemRoulette(player_t *const player, boolean ringbox) K_FillItemRouletteData(player, roulette, ringbox); + if (roulette->autoroulette) + roulette->index = P_RandomRange(PR_AUTOROULETTE, 0, roulette->itemListLen - 1); + if (K_PlayerUsesBotMovement(player) == true) { K_BotPickItemPriority(player); @@ -1581,11 +1595,16 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) if (roulette->elapsed > TICRATE>>1) // Prevent accidental immediate item confirm { - if (roulette->elapsed > TICRATE<<4 || (roulette->eggman && roulette->elapsed > TICRATE*4)) + if (roulette->elapsed > TICRATE<<4 || (roulette->eggman && !roulette->autoroulette && roulette->elapsed > TICRATE*4)) { // Waited way too long, forcefully confirm the item. confirmItem = true; } + else if (roulette->autoroulette) + { + // confirmItem = (roulette->speed > 15); + confirmItem = (roulette->elapsed == TICRATE*2); + } else { // We can stop our item when we choose. @@ -1616,6 +1635,10 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) { // D2 fudge factor. Roulette was originally designed and tested with this delay. UINT8 fudgedDelay = (player->cmd.latency <= 2) ? 0 : player->cmd.latency - 2; + + if (roulette->autoroulette) + fudgedDelay = 0; // We didn't manually stop this, you jackwagon + while (fudgedDelay > 0) { UINT8 gap = (roulette->speed - roulette->tics); // How long has the roulette been on this entry? @@ -1671,6 +1694,11 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) roulette->elapsed++; + /* + if (roulette->autoroulette && (roulette->elapsed % 5 == 0) && (roulette->elapsed > TICRATE)) + roulette->speed++; + */ + if (roulette->tics == 0) { roulette->index = (roulette->index + 1) % roulette->itemListLen; diff --git a/src/m_random.h b/src/m_random.h index 54d3698a8..f3e81f938 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -78,6 +78,8 @@ typedef enum PR_BOTS, // Bot spawning + PR_AUTOROULETTE, // Item box accessibility + PRNUMCLASS } pr_class_t; diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c index 020be1858..b27578c75 100644 --- a/src/menus/options-profiles-1.c +++ b/src/menus/options-profiles-1.c @@ -30,6 +30,7 @@ menu_t OPTIONS_ProfilesDef = { consvar_t cv_dummyprofilename = CVAR_INIT ("dummyprofilename", "", CV_HIDDEN, NULL, NULL); consvar_t cv_dummyprofileplayername = CVAR_INIT ("dummyprofileplayername", "", CV_HIDDEN, NULL, NULL); consvar_t cv_dummyprofilekickstart = CVAR_INIT ("dummyprofilekickstart", "Off", CV_HIDDEN, CV_OnOff, NULL); +consvar_t cv_dummyprofileautoroulette = CVAR_INIT ("dummyprofileautoroulette", "Off", CV_HIDDEN, CV_OnOff, NULL); consvar_t cv_dummyprofilerumble = CVAR_INIT ("dummyprofilerumble", "On", CV_HIDDEN, CV_OnOff, NULL); void M_ProfileSelectInit(INT32 choice) @@ -93,6 +94,7 @@ static void M_StartEditProfile(INT32 c) CV_StealthSet(&cv_dummyprofilename, optionsmenu.profile->profilename); CV_StealthSet(&cv_dummyprofileplayername, optionsmenu.profile->playername); CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel); + CV_StealthSetValue(&cv_dummyprofileautoroulette, optionsmenu.profile->autoroulette); CV_StealthSetValue(&cv_dummyprofilerumble, optionsmenu.profile->rumble); } else @@ -100,6 +102,7 @@ static void M_StartEditProfile(INT32 c) CV_StealthSet(&cv_dummyprofilename, ""); CV_StealthSet(&cv_dummyprofileplayername, ""); CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off + CV_StealthSetValue(&cv_dummyprofileautoroulette, 0); // off CV_StealthSetValue(&cv_dummyprofilerumble, 1); // on } diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 9ef5b590f..dc648abd6 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -91,6 +91,9 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_CONTROL | IT_CVAR, "KICKSTART ACCEL", "Hold A to auto-accel. Tap it to cancel.", NULL, {.cvar = &cv_dummyprofilekickstart}, 0, 0}, + {IT_CONTROL | IT_CVAR, "AUTO ROULETTE", "Item roulette auto-stops on a random result.", + NULL, {.cvar = &cv_dummyprofileautoroulette}, 0, 0}, + {IT_HEADER, "EXTRA", "", NULL, {NULL}, 0, 0}, @@ -187,6 +190,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) SINT8 belongsto = PR_ProfileUsedBy(optionsmenu.profile); // Save the profile optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; + optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value; optionsmenu.profile->rumble = cv_dummyprofilerumble.value; memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault)); @@ -196,6 +200,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) { memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); CV_SetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value); + CV_SetValue(&cv_autoroulette[belongsto], cv_dummyprofileautoroulette.value); CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value); } @@ -213,6 +218,7 @@ void M_ProfileControlsConfirm(INT32 choice) M_ProfileControlSaveResponse(MA_YES); optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; // Make sure to save kickstart accel. + optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value; // We should really just rip this entire construct out at some point optionsmenu.profile->rumble = cv_dummyprofilerumble.value; // And rumble too! // Reapply player 1's real profile. diff --git a/src/p_mobj.c b/src/p_mobj.c index bea139da0..481849eb2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11380,10 +11380,6 @@ void P_RemoveSavegameMobj(mobj_t *mobj) P_UnlinkThinker((thinker_t*)mobj); } -static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "2", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL); -consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); - static void P_SpawnPrecipitationAt(fixed_t basex, fixed_t basey) { INT32 j, k; diff --git a/src/p_saveg.c b/src/p_saveg.c index 9899d7b2d..2c2e3ce11 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -623,6 +623,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, players[i].itemRoulette.elapsed); WRITEUINT8(save->p, players[i].itemRoulette.eggman); WRITEUINT8(save->p, players[i].itemRoulette.ringbox); + WRITEUINT8(save->p, players[i].itemRoulette.autoroulette); // sonicloopsvars_t WRITEFIXED(save->p, players[i].loop.radius); @@ -1058,6 +1059,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].itemRoulette.elapsed = (tic_t)READUINT32(save->p); players[i].itemRoulette.eggman = (boolean)READUINT8(save->p); players[i].itemRoulette.ringbox = (boolean)READUINT8(save->p); + players[i].itemRoulette.autoroulette = (boolean)READUINT8(save->p); // sonicloopsvars_t players[i].loop.radius = READFIXED(save->p); diff --git a/src/st_stuff.c b/src/st_stuff.c index 75c556fd3..c1ff32972 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1306,6 +1306,124 @@ void ST_AskToJoinEnvelope(void) } #endif +static INT32 ST_ServerSplash_OpacityFlag(INT32 opacity) +{ + if (opacity >= NUMTRANSMAPS) + { + return 0; + } + + opacity = max(opacity, 1); + return (NUMTRANSMAPS - opacity) << V_ALPHASHIFT; +} + +void ST_DrawServerSplash(boolean timelimited) +{ + static const fixed_t SPLASH_LEN = (FRACUNIT * TICRATE) * 3; + static const fixed_t SPLASH_WAIT = (FRACUNIT * TICRATE) / 2; + + static fixed_t splashTime = -SPLASH_WAIT; + static char prevContext[8] = {0}; + + if (memcmp(prevContext, server_context, 8) != 0) + { + // Context changed, we want to draw it again + splashTime = -SPLASH_WAIT; + memcpy(prevContext, server_context, 8); + } + + if (lt_ticker < lt_endtime) + { + // Level title is running rn + return; + } + + if (timelimited + && splashTime >= SPLASH_LEN) + { + // We finished drawing it + return; + } + + splashTime += renderdeltatics; + if (splashTime <= 0) + { + // We're waiting a tiny bit to draw it + return; + } + + const INT32 splashTic = splashTime >> FRACBITS; + INT32 opacity = NUMTRANSMAPS; + if (splashTic < NUMTRANSMAPS) + { + opacity = splashTic; + } + else if (timelimited + && splashTic > (SPLASH_LEN >> FRACBITS) - NUMTRANSMAPS) + { + opacity = (SPLASH_LEN >> FRACBITS) - splashTic; + } + + INT32 opacityFlag = ST_ServerSplash_OpacityFlag(opacity); + + patch_t *gridPatch = W_CachePatchName("MOTDBG", PU_CACHE); + + if (gridPatch && gridPatch->width) + { + fixed_t gridX = -(splashTime / 3) % (gridPatch->width * FRACUNIT); + fixed_t gridY = (gridPatch->height) * FRACUNIT; + INT32 gridOpacity = ST_ServerSplash_OpacityFlag(opacity / 2); + fixed_t maxX = (vid.width * FRACUNIT) / vid.dupx; + + while (gridX < maxX) + { + V_DrawFixedPatch( + gridX, gridY, + FRACUNIT, + (V_SNAPTOLEFT|V_SNAPTOBOTTOM) | V_SUBTRACT | V_VFLIP | gridOpacity, + gridPatch, + NULL + ); + + gridX += (gridPatch->width * FRACUNIT); + } + } + + // We're a bit crunched atm to do this but hopefully in the future + // the icon can be made a bmp file on the hard drive that the server + // sends on client join instead. + patch_t *iconPatch = W_CachePatchName("MOTDICON", PU_CACHE); + fixed_t iconX = (BASEVIDWIDTH - 16 - iconPatch->width) * FRACUNIT; + fixed_t iconY = (8) * FRACUNIT; + V_DrawFixedPatch( + iconX, iconY, + FRACUNIT, + (V_SNAPTORIGHT|V_SNAPTOBOTTOM) | opacityFlag, + iconPatch, + NULL + ); + + fixed_t textX = (BASEVIDWIDTH - 16 - 36) * FRACUNIT; + fixed_t textY = (24 - 8) * FRACUNIT; + + V_DrawRightAlignedStringAtFixed( + textX, textY, + (V_SNAPTORIGHT|V_SNAPTOBOTTOM) | opacityFlag, + connectedservername + ); + + textY += 10*FRACUNIT; + + if (connectedservercontact[0] != 0) + { + V_DrawRightAlignedThinStringAtFixed( + textX, textY, + (V_SNAPTORIGHT|V_SNAPTOBOTTOM) | opacityFlag, + va("Contact @ %c%s", '\x80' + cv_shoutcolor.value, connectedservercontact) + ); + } +} + void ST_Drawer(void) { boolean stagetitle = false; // Decide whether to draw the stage title or not diff --git a/src/st_stuff.h b/src/st_stuff.h index 44aa5f251..c406bdcaf 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -75,6 +75,8 @@ void ST_preLevelTitleCardDrawer(void); extern tic_t lt_ticker, lt_lasttic; extern tic_t lt_exitticker, lt_endtime; +void ST_DrawServerSplash(boolean timelimited); + // return if player a is in the same team as player b boolean ST_SameTeam(player_t *a, player_t *b); diff --git a/src/v_video.cpp b/src/v_video.cpp index 17519f894..351ff4d46 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -2789,12 +2789,24 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st V_DrawThinString(x, y, option, string); } -void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { x -= (V_ThinStringWidth(string, option) / 2) * FRACUNIT; V_DrawThinStringAtFixed(x, y, option, string); } +void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +{ + x -= V_StringWidth(string, option) * FRACUNIT; + V_DrawStringAtFixed(x, y, option, string); +} + +void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +{ + x -= (V_StringWidth(string, option) / 2) * FRACUNIT; + V_DrawStringAtFixed(x, y, option, string); +} + void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { x -= V_ThinStringWidth(string, option) * FRACUNIT; diff --git a/src/v_video.h b/src/v_video.h index 7a26591dc..f7c32505c 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -334,16 +334,14 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st #define V_DrawStringAtFixed( x,y,option,string ) \ V__DrawOneScaleString (x,y,FRACUNIT,option,NULL,HU_FONT,string) +void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); +void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawThinStringAtFixed( x,y,option,string ) \ V__DrawOneScaleString (x,y,FRACUNIT,option,NULL,TINY_FONT,string) void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); - -void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); - // Draws a titlecard font string. // timer: when the letters start appearing (leave to 0 to disable) // threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...)