Do a bunch of major modifications to the voting system's rule change system!

* Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency.
	* "Never" - does what it says on the tin.
	* "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full
	* "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps
	* "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change
	* There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense.
* Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps.
* Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.)
This commit is contained in:
toaster 2018-09-11 15:41:41 +01:00
parent e01f2ff096
commit fd7bc1c1ac
6 changed files with 85 additions and 25 deletions

View File

@ -353,6 +353,8 @@ consvar_t cv_kartbumpers = {"kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_
consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}};
consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}};
consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};

View File

@ -125,6 +125,7 @@ extern consvar_t cv_kartbumpers;
extern consvar_t cv_kartfrantic;
extern consvar_t cv_kartcomeback;
extern consvar_t cv_kartencore;
extern consvar_t cv_kartvoterulechanges;
extern consvar_t cv_kartspeedometer;
extern consvar_t cv_kartvoices;

View File

@ -3113,14 +3113,48 @@ boolean G_BattleGametype(void)
//
INT16 G_SometimesGetDifferentGametype(void)
{
if (randmapbuffer[NUMMAPS] != -1)
boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE) && G_RaceGametype());
if (!cv_kartvoterulechanges.value) // never
return gametype;
if (randmapbuffer[NUMMAPS] > 0 && (encorepossible || cv_kartvoterulechanges.value != 3))
{
if (M_SecretUnlocked(SECRET_ENCORE) && (M_RandomChance(FRACUNIT/2/*56*/) != cv_kartencore.value) && G_RaceGametype())
return (gametype|0x80);
if (cv_kartvoterulechanges.value != 1)
randmapbuffer[NUMMAPS]--;
if (encorepossible)
{
switch (cv_kartvoterulechanges.value)
{
case 3: // always
randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set
break;
case 2: // frequent
encorepossible = M_RandomChance(FRACUNIT>>1);
break;
case 1: // sometimes
default:
encorepossible = M_RandomChance(FRACUNIT>>3);
break;
}
if (encorepossible != cv_kartencore.value)
return (gametype|0x80);
}
return gametype;
}
randmapbuffer[NUMMAPS] = gametype;
switch (cv_kartvoterulechanges.value) // okay, we're having a gametype change! when's the next one, luv?
{
case 3: // always
randmapbuffer[NUMMAPS] = 1; // every other vote (or always if !encorepossible)
break;
case 1: // sometimes
default:
// fallthrough - happens when clearing buffer, but needs a reasonable countdown if cvar is modified
case 2: // frequent
randmapbuffer[NUMMAPS] = 5; // per "cup"
break;
}
if (gametype == GT_MATCH)
return GT_RACE;
@ -3188,6 +3222,7 @@ INT16 G_TOLFlag(INT32 pgametype)
return INT16_MAX;
}
#ifdef FLUSHMAPBUFFEREARLY
static INT32 TOLMaps(INT16 tolflags)
{
INT32 num = 0;
@ -3205,6 +3240,7 @@ static INT32 TOLMaps(INT16 tolflags)
return num;
}
#endif
/** Select a random map with the given typeoflevel flags.
* If no map has those flags, this arbitrarily gives you map 1.
@ -3223,6 +3259,8 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb
if (!okmaps)
okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL);
tryagain:
// Find all the maps that are ok and and put them in an array.
for (ix = 0; ix < NUMMAPS; ix++)
{
@ -3256,12 +3294,28 @@ INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignoreb
okmaps[numokmaps++] = ix;
}
if (numokmaps == 0)
if (numokmaps == 0) // If there's no matches... (Goodbye, incredibly silly function chains :V)
{
if (!ignorebuffer)
return G_RandMap(tolflags, pprevmap, dontadd, true, maphell, callagainsoon); // If there's no matches, (An incredibly silly function chain, buuut... :V)
if (maphell)
return G_RandMap(tolflags, pprevmap, dontadd, true, maphell-1, callagainsoon);
{
if (randmapbuffer[3] == -1) // Is the buffer basically empty?
{
ignorebuffer = true; // This will probably only help in situations where there's very few maps, but it's folly not to at least try it
goto tryagain; //return G_RandMap(tolflags, pprevmap, dontadd, true, maphell, callagainsoon);
}
for (bufx = 3; bufx < NUMMAPS; bufx++) // Let's clear all but the three most recent maps...
randmapbuffer[bufx] = -1;
if (cv_kartvoterulechanges.value == 1) // sometimes
randmapbuffer[NUMMAPS] = 0;
goto tryagain; //return G_RandMap(tolflags, pprevmap, dontadd, ignorebuffer, maphell, callagainsoon);
}
if (maphell) // Any wiggle room to loosen our restrictions here?
{
maphell--;
goto tryagain; //return G_RandMap(tolflags, pprevmap, dontadd, true, maphell-1, callagainsoon);
}
ix = 0; // Sorry, none match. You get MAP01.
for (bufx = 0; bufx < NUMMAPS+1; bufx++)
@ -3423,11 +3477,15 @@ static void G_DoCompleted(void)
automapactive = false;
if (randmapbuffer[TOLMaps(G_TOLFlag(gametype))-4] != -1) // we're getting pretty full, so lets clear it
#ifdef FLUSHMAPBUFFEREARLY
if (randmapbuffer[TOLMaps(G_TOLFlag(gametype))-5] != -1) // We're getting pretty full, so! -- no need for this, handled in G_RandMap
{
for (i = 0; i < NUMMAPS+1; i++)
for (i = 3; i < NUMMAPS; i++) // Let's clear all but the three most recent maps...
randmapbuffer[i] = -1;
if (cv_kartvoterulechanges.value == 1) // sometimes
randmapbuffer[NUMMAPS] = 0;
}
#endif
if (gametype != GT_COOP)
{

View File

@ -402,6 +402,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartfrantic);
CV_RegisterVar(&cv_kartcomeback);
CV_RegisterVar(&cv_kartencore);
CV_RegisterVar(&cv_kartvoterulechanges);
CV_RegisterVar(&cv_kartspeedometer);
CV_RegisterVar(&cv_kartvoices);
CV_RegisterVar(&cv_karteliminatelast);

View File

@ -1474,14 +1474,15 @@ static menuitem_t OP_ServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 40},
{IT_STRING | IT_CVAR, NULL, "Map Progression", &cv_advancemap, 50},
{IT_STRING | IT_CVAR, NULL, "Voting Timer", &cv_votetime, 60},
{IT_STRING | IT_CVAR, NULL, "Voting Rule Changes", &cv_kartvoterulechanges, 70},
#ifndef NONET
{IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 80},
{IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 90},
//{IT_STRING | IT_CVAR, NULL, "Join on Map Change", &cv_joinnextround, 100},
{IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 90},
{IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 100},
//{IT_STRING | IT_CVAR, NULL, "Join on Map Change", &cv_joinnextround, 110},
{IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 100},
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 110},
{IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 110},
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 120},
#endif
};

View File

@ -1548,13 +1548,13 @@ static void Y_UnloadVoteData(void)
//
void Y_SetupVoteFinish(SINT8 pick, SINT8 level)
{
if (!voteclient.loaded)
return;
if (pick == -1) // No other votes? We gotta get out of here, then!
{
if (voteclient.loaded)
{
Y_EndVote();
Y_FollowIntermission();
}
Y_EndVote();
Y_FollowIntermission();
return;
}
@ -1600,11 +1600,8 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level)
}
else if (endtype == 0) // Might as well put this here, too.
{
if (voteclient.loaded)
{
Y_EndVote();
Y_FollowIntermission();
}
Y_EndVote();
Y_FollowIntermission();
return;
}
else