From 59730c5db61c763d75f8262bb4b755871e7fb552 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 3 Feb 2019 16:43:11 -0500 Subject: [PATCH 1/6] In-game player cap & spectator queue Force everyone beyond a certain point to spectate -- spectators get to queue up. In response to me doing a 1v1 match, tons of people wanting to join to watch, and just relying on honor system to prevent mid-joiners. Spectators are prioritized by how long they've been waiting. I'm thinking of hijacking base SRB2's team scramble for a scramble option later. --- src/d_netcmd.c | 4 ++++ src/d_netcmd.h | 2 +- src/d_player.h | 1 + src/dehacked.c | 3 ++- src/k_kart.c | 64 +++++++++++++++++++++++++++++++++++++++++--------- src/p_user.c | 2 ++ src/st_stuff.c | 39 +++++++++++++++++------------- 7 files changed, 86 insertions(+), 29 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 775f2225..5773d590 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -236,6 +236,9 @@ static consvar_t cv_dummyconsvar = {"dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP consvar_t cv_restrictskinchange = {"restrictskinchange", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowteamchange = {"allowteamchange", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t ingamecap_cons_t[] = {{0, "MIN"}, {MAXPLAYERS-1, "MAX"}, {0, NULL}}; +consvar_t cv_ingamecap = {"ingamecap", "0", CV_NETVAR, ingamecap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, startingliveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t respawntime_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}}; @@ -642,6 +645,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_allowexitlevel); CV_RegisterVar(&cv_restrictskinchange); CV_RegisterVar(&cv_allowteamchange); + CV_RegisterVar(&cv_ingamecap); CV_RegisterVar(&cv_respawntime); CV_RegisterVar(&cv_killingdead); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 2269996f..c590eee6 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -93,7 +93,7 @@ extern consvar_t cv_mute; extern consvar_t cv_killingdead; extern consvar_t cv_pause; -extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_respawntime; +extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_ingamecap, cv_respawntime; /*extern consvar_t cv_teleporters, cv_superring, cv_supersneakers, cv_invincibility; extern consvar_t cv_jumpshield, cv_watershield, cv_ringshield, cv_forceshield, cv_bombshield; diff --git a/src/d_player.h b/src/d_player.h index 27fdef8d..58d2df4b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -352,6 +352,7 @@ typedef enum k_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator k_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items) k_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed + k_spectatewait, // How long have you been waiting as a spectator NUMKARTSTUFF } kartstufftype_t; diff --git a/src/dehacked.c b/src/dehacked.c index b9e29bc4..67080bd7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8299,7 +8299,8 @@ static const char *const KARTSTUFF_LIST[] = { "ITEMBLINK", "ITEMBLINKMODE", - "GETSPARKS" + "GETSPARKS", + "SPECTATEWAIT" }; static const char *const HUDITEMS_LIST[] = { diff --git a/src/k_kart.c b/src/k_kart.c index dde4849e..8cb0941e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5744,9 +5744,22 @@ void K_CheckBumpers(void) void K_CheckSpectateStatus(void) { UINT8 respawnlist[MAXPLAYERS]; - UINT8 i, numingame = 0, numjoiners = 0; + UINT8 i, j, numingame = 0, numjoiners = 0; - if (!cv_allowteamchange.value) return; + // Maintain spectate wait timer + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (players[i].spectator && (players[i].pflags & PF_WANTSTOJOIN)) + players[i].kartstuff[k_spectatewait]++; + else + players[i].kartstuff[k_spectatewait] = 0; + } + + // No one's allowed to join + if (!cv_allowteamchange.value) + return; // Get the number of players in game, and the players to be de-spectated. for (i = 0; i < MAXPLAYERS; i++) @@ -5757,16 +5770,18 @@ void K_CheckSpectateStatus(void) if (!players[i].spectator) { numingame++; + if (cv_ingamecap.value && numingame >= cv_ingamecap.value) // DON'T allow if you've hit the in-game player cap + return; if (gamestate != GS_LEVEL) // Allow if you're not in a level - continue; + continue; if (players[i].exiting) // DON'T allow if anyone's exiting return; if (numingame < 2 || leveltime < starttime || mapreset) // Allow if the match hasn't started yet - continue; + continue; if (leveltime > (starttime + 20*TICRATE)) // DON'T allow if the match is 20 seconds in - return; - if (G_RaceGametype() && players[i].laps) // DON'T allow if the race is at 2 laps - return; + return; + if (G_RaceGametype() && players[i].laps) // DON'T allow if the race is at 2 laps + return; continue; } else if (!(players[i].pflags & PF_WANTSTOJOIN)) @@ -5779,16 +5794,43 @@ void K_CheckSpectateStatus(void) if (!numjoiners) return; - // Reset the match if you're in an empty server - if (!mapreset && gamestate == GS_LEVEL && leveltime >= starttime && (numingame < 2 && numingame+numjoiners >= 2)) + // Organize by spectate wait timer { - S_ChangeMusicInternal("chalng", false); // COME ON - mapreset = 3*TICRATE; // Even though only the server uses this for game logic, set for everyone for HUD in the future + UINT8 oldrespawnlist[MAXPLAYERS]; + + for (i = 0; i < numjoiners; i++) // copy old table before modifying + oldrespawnlist[i] = respawnlist[i]; + + for (i = 0; i < numjoiners; i++) + { + UINT8 pos = 0; + + for (j = 0; j < numjoiners; j++) + { + if (j == i) + continue; + if (players[oldrespawnlist[j]].kartstuff[k_spectatewait] > players[oldrespawnlist[i]].kartstuff[k_spectatewait]) + pos++; + } + + respawnlist[pos] = oldrespawnlist[i]; + } } // Finally, we can de-spectate everyone! for (i = 0; i < numjoiners; i++) + { + if (cv_ingamecap.value && numingame+i >= cv_ingamecap.value) // Hit the in-game player cap while adding people? + break; P_SpectatorJoinGame(&players[respawnlist[i]]); + } + + // Reset the match if you're in an empty server + if (!mapreset && gamestate == GS_LEVEL && leveltime >= starttime && (numingame < 2 && numingame+i >= 2)) // use previous i value + { + S_ChangeMusicInternal("chalng", false); // COME ON + mapreset = 3*TICRATE; // Even though only the server uses this for game logic, set for everyone for HUD + } } //} diff --git a/src/p_user.c b/src/p_user.c index d7423d80..0978a0da 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8763,6 +8763,7 @@ boolean P_SpectatorJoinGame(player_t *player) } player->spectator = false; player->pflags &= ~PF_WANTSTOJOIN; + player->kartstuff[k_spectatewait] = 0; player->ctfteam = changeto; player->playerstate = PST_REBORN; @@ -8787,6 +8788,7 @@ boolean P_SpectatorJoinGame(player_t *player) } player->spectator = false; player->pflags &= ~PF_WANTSTOJOIN; + player->kartstuff[k_spectatewait] = 0; player->playerstate = PST_REBORN; //Reset away view diff --git a/src/st_stuff.c b/src/st_stuff.c index 8ebd2132..36a658ae 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1952,31 +1952,38 @@ static void ST_overlayDrawer(void) #endif ) { + const char *itemtxt = M_GetText("Item - Join Game"); + + if (stplyr->powers[pw_flashing]) + itemtxt = M_GetText("Item - . . ."); + else if (stplyr->pflags & PF_WANTSTOJOIN) + itemtxt = M_GetText("Item - Cancel Join"); + else if (G_GametypeHasTeams()) + itemtxt = M_GetText("Item - Join Team"); + + if (cv_ingamecap.value) + { + UINT8 numingame = 0; + UINT8 i; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && !players[i].spectator) + numingame++; + + itemtxt = va("%s (%s: %d)", itemtxt, M_GetText("Slots left"), max(0, cv_ingamecap.value - numingame)); + } + // SRB2kart: changed positions & text if (splitscreen) { INT32 splitflags = K_calcSplitFlags(0); V_DrawThinString(2, (BASEVIDHEIGHT/2)-20, V_YELLOWMAP|V_HUDTRANSHALF|splitflags, M_GetText("- SPECTATING -")); - if (stplyr->powers[pw_flashing]) - V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - . . .")); - else if (stplyr->pflags & PF_WANTSTOJOIN) - V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Cancel Join")); - /*else if (G_GametypeHasTeams()) - V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Team"));*/ - else - V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Game")); + V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, itemtxt); } else { V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -")); - if (stplyr->powers[pw_flashing]) - V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - . . .")); - else if (stplyr->pflags & PF_WANTSTOJOIN) - V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Cancel Join")); - /*else if (G_GametypeHasTeams()) - V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/ - else - V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Game")); + V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, itemtxt); V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF, M_GetText("Accelerate - Float")); V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF, M_GetText("Brake - Sink")); } From a6ac6ecdc57970a997a322e28eef93ef275143cf Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 3 Feb 2019 17:15:33 -0500 Subject: [PATCH 2/6] Missed this --- src/k_kart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_kart.c b/src/k_kart.c index 8cb0941e..d77c76fa 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5795,6 +5795,7 @@ void K_CheckSpectateStatus(void) return; // Organize by spectate wait timer + if (cv_ingamecap.value) { UINT8 oldrespawnlist[MAXPLAYERS]; From 068ee93422a8db4d037aeead2327ac2284e8f558 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 3 Feb 2019 23:09:09 +0000 Subject: [PATCH 3/6] gotta break a few eggboxes to fix a crash --- src/k_kart.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 37c70681..218e8c6f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3021,7 +3021,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map newz = player->mo->z; } - mo = P_SpawnMobj(newx, newy, newz, mapthing); + mo = P_SpawnMobj(newx, newy, newz, mapthing); // this will never return null because collision isn't processed here if (P_MobjFlip(player->mo) < 0) mo->z = player->mo->z + player->mo->height - mo->height; @@ -3033,7 +3033,9 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map { // floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn // This should set it for FOFs - P_TeleportMove(mo, mo->x, mo->y, mo->z); + P_TeleportMove(mo, mo->x, mo->y, mo->z); // however, THIS can fuck up your day. just absolutely ruin you. + if (P_MobjWasRemoved(mo)) + return NULL; if (P_MobjFlip(mo) > 0) { @@ -3051,11 +3053,8 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map } } - if (mo) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->eflags |= MFE_VERTICALFLIP; - } + if (player->mo->eflags & MFE_VERTICALFLIP) + mo->eflags |= MFE_VERTICALFLIP; } } From 503e4f977f231665cbd9891b05027f8a925346f2 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 3 Feb 2019 23:37:19 +0000 Subject: [PATCH 4/6] Show WANTED and minimap in battle splits even when p1 is nuked. --- src/k_kart.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 218e8c6f..755f3802 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8348,14 +8348,6 @@ void K_drawKartHUD(void) || ((splitscreen > 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase)) K_drawKartFirstPerson(); -/* if (splitscreen == 2) // Player 4 in 3P is the minimap :p - { -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_minimap)) -#endif - K_drawKartMinimap(); - }*/ - // Draw full screen stuff that turns off the rest of the HUD if (mapreset && stplyr == &players[displayplayer]) { @@ -8371,7 +8363,9 @@ void K_drawKartHUD(void) && stplyr->playerstate == PST_LIVE))) { K_drawBattleFullscreen(); - return; + if (!splitscreen) + return; + isfreeplay = true; // variable reuse, since isfreeplay will not be otherwise set until after everything we want to happen } // Draw the CHECK indicator before the other items, so it's overlapped by everything else @@ -8392,10 +8386,12 @@ void K_drawKartHUD(void) #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_minimap)) #endif - K_drawKartMinimap(); // 3P splitscreen is handled above - + K_drawKartMinimap(); } + if (isfreeplay) + return; + // Draw the item window #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_item)) From 55bb82eae8ad1367580840c807792e50932baac1 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 3 Feb 2019 23:50:02 +0000 Subject: [PATCH 5/6] Change order of operations so that fullscreen stuff is done in front of minimap, to match other two/three players in 3/4p. --- src/k_kart.c | 59 ++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 755f3802..e59fbfc9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8336,6 +8336,7 @@ static void K_drawCheckpointDebugger(void) void K_drawKartHUD(void) { boolean isfreeplay = false; + boolean battlefullscreen = false; // Define the X and Y for each drawn object // This is handled by console/menu values @@ -8355,42 +8356,42 @@ void K_drawKartHUD(void) return; } - if ((G_BattleGametype()) + battlefullscreen = ((G_BattleGametype()) && (stplyr->exiting || (stplyr->kartstuff[k_bumper] <= 0 && stplyr->kartstuff[k_comebacktimer] && comeback - && stplyr->playerstate == PST_LIVE))) + && stplyr->playerstate == PST_LIVE))); + + if (!battlefullscreen || splitscreen) + { + // Draw the CHECK indicator before the other items, so it's overlapped by everything else + if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting) + K_drawKartPlayerCheck(); + + // Draw WANTED status + if (G_BattleGametype()) + { +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_wanted)) +#endif + K_drawKartWanted(); + } + + if (cv_kartminimap.value && !titledemo) + { +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_minimap)) +#endif + K_drawKartMinimap(); + } + } + + if (battlefullscreen) { K_drawBattleFullscreen(); - if (!splitscreen) - return; - isfreeplay = true; // variable reuse, since isfreeplay will not be otherwise set until after everything we want to happen - } - - // Draw the CHECK indicator before the other items, so it's overlapped by everything else - if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting) - K_drawKartPlayerCheck(); - - // Draw WANTED status - if (G_BattleGametype()) - { -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_wanted)) -#endif - K_drawKartWanted(); - } - - if (cv_kartminimap.value && !titledemo) - { -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_minimap)) -#endif - K_drawKartMinimap(); - } - - if (isfreeplay) return; + } // Draw the item window #ifdef HAVE_BLUA From fd529f93634252ed254c69d4c3439cfb34ba516e Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 3 Feb 2019 23:23:41 -0500 Subject: [PATCH 6/6] fickle suggestions --- src/k_kart.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 51bbccbb..b877e13f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5808,19 +5808,20 @@ void K_CheckSpectateStatus(void) if (cv_ingamecap.value) { UINT8 oldrespawnlist[MAXPLAYERS]; - - for (i = 0; i < numjoiners; i++) // copy old table before modifying - oldrespawnlist[i] = respawnlist[i]; - + memcpy(oldrespawnlist, respawnlist, numjoiners); for (i = 0; i < numjoiners; i++) { UINT8 pos = 0; + INT32 ispecwait = players[oldrespawnlist[i]].kartstuff[k_spectatewait]; for (j = 0; j < numjoiners; j++) { + INT32 jspecwait = players[oldrespawnlist[j]].kartstuff[k_spectatewait]; if (j == i) continue; - if (players[oldrespawnlist[j]].kartstuff[k_spectatewait] > players[oldrespawnlist[i]].kartstuff[k_spectatewait]) + if (jspecwait > ispecwait) + pos++; + else if (jspecwait == ispecwait && j < i) pos++; }