Rework the map command suite a little
The following funcs are now a suite with almost-identical argument lists.
- `map` is for immediately going to a map
- Add `-random`/`-r`
- `queuemap` is for interacting with the live Round Queue
- Add `-random`/`-r`
- Performed server-side
- `-clear` and `-show` now accept partial params `-c` and `-s`
- Fix minor error with 0-argument print's text
- `showmap` is for printing information
- Add arbitrary map name/ID input
- `showmap robo` prints the course `map robo` would resolve to
- Add `-gametype`/`-gt`/`-g`
- For compatibility testing
- Add `-random`/`-r`
- Combine with `-gametype` for extra guarantees
- `randommap` was deprecated
- Will only print replacement instructions of `map -random`, and nothing else
This commit is contained in:
parent
dd98ee93e2
commit
02ba3e2557
2 changed files with 267 additions and 119 deletions
|
|
@ -5808,7 +5808,6 @@ static void PT_ReqMapQueue(int node)
|
|||
CONS_Alert(CONS_ERROR, "Recieved REQMAPQUEUE, but unable to add map beyond %u\n", roundqueue.size);
|
||||
|
||||
// But this one does, because otherwise it's silent failure!
|
||||
// Todo print the map's name, maybe?
|
||||
char rejectmsg[256];
|
||||
strlcpy(rejectmsg, "The server couldn't queue your chosen map.", 256);
|
||||
SendServerNotice(reqmapqueue.source, rejectmsg);
|
||||
|
|
@ -5816,6 +5815,43 @@ static void PT_ReqMapQueue(int node)
|
|||
return;
|
||||
}
|
||||
|
||||
if (reqmapqueue.newmapnum == NEXTMAP_VOTING)
|
||||
{
|
||||
/*UINT8 numPlayers = 0, i;
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
extern consvar_t cv_forcebots; // debug
|
||||
|
||||
if (!(gametypes[reqmapqueue.newgametype]->rules & GTR_BOTS) && players[i].bot && !cv_forcebots.value)
|
||||
{
|
||||
// Gametype doesn't support bots
|
||||
continue;
|
||||
}
|
||||
|
||||
numPlayers++;
|
||||
}*/
|
||||
|
||||
reqmapqueue.newmapnum = G_RandMap(G_TOLFlag(reqmapqueue.newgametype), UINT16_MAX, false, 0, false, NULL);
|
||||
}
|
||||
|
||||
if (reqmapqueue.newmapnum >= nummapheaders)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Recieved REQMAPQUEUE, but unable to add map of invalid ID (%u)\n", reqmapqueue.newmapnum);
|
||||
|
||||
char rejectmsg[256];
|
||||
strlcpy(rejectmsg, "The server couldn't queue your chosen map.", 256);
|
||||
SendServerNotice(reqmapqueue.source, rejectmsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
G_AddMapToBuffer(reqmapqueue.newmapnum);
|
||||
|
||||
UINT8 buf[1+2+1];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
|
|
|
|||
348
src/d_netcmd.c
348
src/d_netcmd.c
|
|
@ -3653,6 +3653,7 @@ static void Command_Map_f(void)
|
|||
size_t option_force;
|
||||
size_t option_gametype;
|
||||
size_t option_encore;
|
||||
size_t option_random;
|
||||
size_t option_skill;
|
||||
boolean newresetplayers;
|
||||
boolean newforcespecialstage;
|
||||
|
|
@ -3661,7 +3662,7 @@ static void Command_Map_f(void)
|
|||
|
||||
INT32 newmapnum;
|
||||
|
||||
char * mapname;
|
||||
char * mapname = NULL;
|
||||
char *realmapname = NULL;
|
||||
|
||||
INT32 newgametype = gametype;
|
||||
|
|
@ -3676,6 +3677,7 @@ static void Command_Map_f(void)
|
|||
option_force = COM_CheckPartialParm("-f");
|
||||
option_gametype = COM_CheckPartialParm("-g");
|
||||
option_encore = COM_CheckPartialParm("-e");
|
||||
option_random = COM_CheckPartialParm("-r");
|
||||
option_skill = COM_CheckPartialParm("-s");
|
||||
newresetplayers = ! COM_CheckParm("-noresetplayers");
|
||||
newforcespecialstage = COM_CheckParm("-forcespecialstage");
|
||||
|
|
@ -3715,31 +3717,17 @@ static void Command_Map_f(void)
|
|||
if (!( first_option = COM_FirstOption() ))
|
||||
first_option = COM_Argc();
|
||||
|
||||
if (first_option < 2)
|
||||
if (!option_random && first_option < 2)
|
||||
{
|
||||
/* I'm going over the fucking lines and I DON'T CAREEEEE */
|
||||
CONS_Printf("map <name / [MAP]code / number> [-gametype <type>] [-force]:\n");
|
||||
CONS_Printf("map <name / number> [-gametype <type>] [-force] / [-random]:\n");
|
||||
CONS_Printf(M_GetText(
|
||||
"Warp to a map, by its name, two character code, with optional \"MAP\" prefix, or by its number (though why would you).\n"
|
||||
"All parameters are case-insensitive and may be abbreviated.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
mapname = ConcatCommandArgv(1, first_option);
|
||||
|
||||
newmapnum = G_FindMapByNameOrCode(mapname, &realmapname);
|
||||
|
||||
if (newmapnum == 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not find any map described as '%s'.\n"), mapname);
|
||||
Z_Free(mapname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mustmodifygame && option_force)
|
||||
{
|
||||
G_SetGameModified(multiplayer, true);
|
||||
}
|
||||
boolean getgametypefrommap = false;
|
||||
|
||||
// new gametype value
|
||||
// use current one by default
|
||||
|
|
@ -3751,15 +3739,23 @@ static void Command_Map_f(void)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (!Playing())
|
||||
else if (option_random)
|
||||
{
|
||||
newresetplayers = true;
|
||||
if (mapheaderinfo[newmapnum-1])
|
||||
if (!Playing())
|
||||
{
|
||||
// Let's just guess so we don't have to specify the gametype EVERY time...
|
||||
newgametype = (mapheaderinfo[newmapnum-1]->typeoflevel & TOL_RACE) ? GT_RACE : GT_BATTLE;
|
||||
CONS_Printf("Can't use -random from the menu without -gametype.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!Playing() || (netgame == false && grandprixinfo.gp == true))
|
||||
{
|
||||
getgametypefrommap = true;
|
||||
}
|
||||
|
||||
if (mustmodifygame && option_force)
|
||||
{
|
||||
G_SetGameModified(multiplayer, true);
|
||||
}
|
||||
|
||||
// new encoremode value
|
||||
if (option_encore)
|
||||
|
|
@ -3773,11 +3769,69 @@ static void Command_Map_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (!option_force && newgametype == gametype && Playing()) // SRB2Kart
|
||||
if (option_random)
|
||||
{
|
||||
//UINT8 numPlayers = 0;
|
||||
UINT16 oldmapnum = UINT16_MAX;
|
||||
|
||||
if (Playing())
|
||||
{
|
||||
//UINT8 i;
|
||||
/*for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
extern consvar_t cv_forcebots; // debug
|
||||
|
||||
if (!(gametypes[newgametype]->rules & GTR_BOTS) && players[i].bot && !cv_forcebots.value)
|
||||
{
|
||||
// Gametype doesn't support bots
|
||||
continue;
|
||||
}
|
||||
|
||||
numPlayers++;
|
||||
} */
|
||||
|
||||
oldmapnum = (gamestate == GS_LEVEL)
|
||||
? (gamemap-1)
|
||||
: prevmap;
|
||||
}
|
||||
|
||||
newmapnum = G_RandMap(G_TOLFlag(newgametype), oldmapnum, false, 0, false, NULL) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapname = ConcatCommandArgv(1, first_option);
|
||||
|
||||
newmapnum = G_FindMapByNameOrCode(mapname, &realmapname);
|
||||
|
||||
if (newmapnum == 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not find any map described as '%s'.\n"), mapname);
|
||||
Z_Free(mapname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (getgametypefrommap)
|
||||
{
|
||||
if (mapheaderinfo[newmapnum-1])
|
||||
{
|
||||
// Let's just guess so we don't have to specify the gametype EVERY time...
|
||||
newgametype = (mapheaderinfo[newmapnum-1]->typeoflevel & TOL_RACE) ? GT_RACE : GT_BATTLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
newresetplayers = true;
|
||||
else if (!option_force && newgametype == gametype) // SRB2Kart
|
||||
newresetplayers = false; // if not forcing and gametypes is the same
|
||||
|
||||
// don't use a gametype the map doesn't support
|
||||
if (cht_debug || option_force || cv_skipmapcheck.value)
|
||||
if (option_random || cht_debug || option_force || cv_skipmapcheck.value)
|
||||
{
|
||||
// The player wants us to trek on anyway. Do so.
|
||||
}
|
||||
|
|
@ -4081,46 +4135,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
|
|||
|
||||
static void Command_RandomMap(void)
|
||||
{
|
||||
INT32 oldmapnum;
|
||||
INT32 newmapnum;
|
||||
INT32 newgametype;
|
||||
boolean newencoremode;
|
||||
boolean newresetplayers;
|
||||
|
||||
if (client && !IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Handle singleplayer conditions.
|
||||
// The existing ones are way too annoyingly complicated and "anti-cheat" for my tastes.
|
||||
|
||||
if (Playing())
|
||||
{
|
||||
newgametype = gametype;
|
||||
newencoremode = encoremode;
|
||||
newresetplayers = false;
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
oldmapnum = gamemap-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldmapnum = prevmap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newgametype = cv_newgametype.value;
|
||||
newencoremode = false;
|
||||
newresetplayers = true;
|
||||
oldmapnum = NEXTMAP_INVALID;
|
||||
}
|
||||
|
||||
newmapnum = G_RandMap(G_TOLFlag(newgametype), oldmapnum, true, 0, false, NULL) + 1;
|
||||
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false);
|
||||
CONS_Printf("randommap is deprecated, please use \"map -random\" instead.\n");
|
||||
}
|
||||
|
||||
static void Command_RestartLevel(void)
|
||||
|
|
@ -4172,13 +4187,11 @@ static void Command_QueueMap_f(void)
|
|||
size_t option_encore;
|
||||
size_t option_clear;
|
||||
size_t option_show;
|
||||
|
||||
boolean usingcheats;
|
||||
boolean ischeating;
|
||||
size_t option_random;
|
||||
|
||||
INT32 newmapnum;
|
||||
|
||||
char * mapname;
|
||||
char * mapname = NULL;
|
||||
char *realmapname = NULL;
|
||||
|
||||
INT32 newgametype = gametype;
|
||||
|
|
@ -4196,19 +4209,10 @@ static void Command_QueueMap_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
usingcheats = CV_CheatsEnabled();
|
||||
ischeating = (!(netgame || multiplayer) || !K_CanChangeRules(false));
|
||||
|
||||
option_clear = COM_CheckParm("-clear");
|
||||
option_clear = COM_CheckPartialParm("-c");
|
||||
|
||||
if (option_clear)
|
||||
{
|
||||
if (ischeating && !usingcheats)
|
||||
{
|
||||
CONS_Printf(M_GetText("Cheats must be enabled.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (roundqueue.size == 0)
|
||||
{
|
||||
CONS_Printf(M_GetText("Round queue is already empty!\n"));
|
||||
|
|
@ -4219,16 +4223,10 @@ static void Command_QueueMap_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
option_show = COM_CheckParm("-show");
|
||||
option_show = COM_CheckPartialParm("-s");
|
||||
|
||||
if (option_show)
|
||||
{
|
||||
if (ischeating && !usingcheats)
|
||||
{
|
||||
CONS_Printf(M_GetText("Cheats must be enabled.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
Handle_MapQueueSend(0, ROUNDQUEUE_CMD_SHOW, false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -4242,44 +4240,21 @@ static void Command_QueueMap_f(void)
|
|||
option_force = COM_CheckPartialParm("-f");
|
||||
option_gametype = COM_CheckPartialParm("-g");
|
||||
option_encore = COM_CheckPartialParm("-e");
|
||||
option_random = COM_CheckPartialParm("-r");
|
||||
|
||||
if (!( first_option = COM_FirstOption() ))
|
||||
first_option = COM_Argc();
|
||||
|
||||
if (first_option < 2)
|
||||
if (!option_random && first_option < 2)
|
||||
{
|
||||
/* I'm going over the fucking lines and I DON'T CAREEEEE */
|
||||
CONS_Printf("queuemap <name / number> [-gametype <type>] [-force] / [-clear] / [-spoil]:\n");
|
||||
CONS_Printf("queuemap <name / number> [-gametype <type>] [-force] / [-random] / [-clear] / [-show]:\n");
|
||||
CONS_Printf(M_GetText(
|
||||
"Queue up a map by its name, or by its number (though why would you).\n"
|
||||
"All parameters are case-insensitive and may be abbreviated.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
mapname = ConcatCommandArgv(1, first_option);
|
||||
|
||||
newmapnum = G_FindMapByNameOrCode(mapname, &realmapname);
|
||||
|
||||
if (newmapnum == 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not find any map described as '%s'.\n"), mapname);
|
||||
Z_Free(mapname);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((/*newmapnum != 1 &&*/ M_MapLocked(newmapnum)))
|
||||
{
|
||||
ischeating = true;
|
||||
}
|
||||
|
||||
if (ischeating && !usingcheats)
|
||||
{
|
||||
CONS_Printf(M_GetText("Cheats must be enabled.\n"));
|
||||
Z_Free(realmapname);
|
||||
Z_Free(mapname);
|
||||
return;
|
||||
}
|
||||
|
||||
// new gametype value
|
||||
// use current one by default
|
||||
if (option_gametype)
|
||||
|
|
@ -4298,17 +4273,34 @@ static void Command_QueueMap_f(void)
|
|||
{
|
||||
newencoremode = !newencoremode;
|
||||
|
||||
if (!M_SecretUnlocked(SECRET_ENCORE) && newencoremode == true && !usingcheats)
|
||||
if (!M_SecretUnlocked(SECRET_ENCORE) && newencoremode == true && !option_force)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You haven't unlocked Encore Mode yet!\n"));
|
||||
Z_Free(realmapname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (option_random)
|
||||
{
|
||||
// Unlike map -random, this is a server side RNG roll
|
||||
newmapnum = NEXTMAP_VOTING + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapname = ConcatCommandArgv(1, first_option);
|
||||
|
||||
newmapnum = G_FindMapByNameOrCode(mapname, &realmapname);
|
||||
|
||||
if (newmapnum == 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not find any map described as '%s'.\n"), mapname);
|
||||
Z_Free(mapname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// don't use a gametype the map doesn't support
|
||||
if (cht_debug || option_force || cv_skipmapcheck.value)
|
||||
if (option_random || cht_debug || option_force || cv_skipmapcheck.value)
|
||||
{
|
||||
// The player wants us to trek on anyway. Do so.
|
||||
}
|
||||
|
|
@ -6702,12 +6694,105 @@ retryscramble:
|
|||
|
||||
static void Command_Showmap_f(void)
|
||||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
UINT16 printmap = NEXTMAP_INVALID;
|
||||
|
||||
size_t first_option;
|
||||
size_t option_random;
|
||||
size_t option_gametype;
|
||||
|
||||
INT32 newgametype = gametype;
|
||||
|
||||
char * mapname = NULL;
|
||||
char *realmapname = NULL;
|
||||
|
||||
option_gametype = COM_CheckPartialParm("-g");
|
||||
option_random = COM_CheckPartialParm("-r");
|
||||
|
||||
if (!( first_option = COM_FirstOption() ))
|
||||
first_option = COM_Argc();
|
||||
|
||||
if (option_gametype)
|
||||
{
|
||||
newgametype = GetGametypeParm(option_gametype);
|
||||
if (newgametype == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (option_random)
|
||||
{
|
||||
UINT8 numPlayers = 0;
|
||||
UINT16 oldmapnum = UINT16_MAX;
|
||||
if (Playing())
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
extern consvar_t cv_forcebots; // debug
|
||||
|
||||
if (!(gametypes[newgametype]->rules & GTR_BOTS) && players[i].bot && !cv_forcebots.value)
|
||||
{
|
||||
// Gametype doesn't support bots
|
||||
continue;
|
||||
}
|
||||
|
||||
numPlayers++;
|
||||
}
|
||||
|
||||
oldmapnum = (gamestate == GS_LEVEL)
|
||||
? (gamemap-1)
|
||||
: prevmap;
|
||||
}
|
||||
else if (!option_gametype)
|
||||
{
|
||||
CONS_Printf("Can't use -random from the menu without -gametype.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printmap = G_RandMap(G_TOLFlag(newgametype), oldmapnum, false, 0, false, NULL);
|
||||
}
|
||||
else if (first_option < 2)
|
||||
{
|
||||
if (!Playing())
|
||||
{
|
||||
CONS_Printf(M_GetText("You must be in a game to use this.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
printmap = (gamestate == GS_LEVEL)
|
||||
? gamemap-1
|
||||
: prevmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapname = ConcatCommandArgv(1, first_option);
|
||||
|
||||
printmap = G_FindMapByNameOrCode(mapname, &realmapname);
|
||||
|
||||
if (printmap == 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Could not find any map described as '%s'.\n"), mapname);
|
||||
Z_Free(mapname);
|
||||
return;
|
||||
}
|
||||
|
||||
printmap--; // i hate the gamemap off-by-one system
|
||||
}
|
||||
|
||||
if (printmap < nummapheaders && mapheaderinfo[printmap])
|
||||
{
|
||||
char *title = G_BuildMapTitle(printmap + 1);
|
||||
|
||||
if (mapheaderinfo[gamemap-1]->zonttl[0] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
{
|
||||
if (mapheaderinfo[gamemap-1]->actnum[0])
|
||||
CONS_Printf("%s (%d): %s %s %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum);
|
||||
CONS_Printf("%s (%d): %s %s %s", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum);
|
||||
else
|
||||
CONS_Printf("%s (%d): %s %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl);
|
||||
}
|
||||
|
|
@ -6718,9 +6803,36 @@ static void Command_Showmap_f(void)
|
|||
else
|
||||
CONS_Printf("%s (%d): %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl);
|
||||
}
|
||||
|
||||
Z_Free(title);
|
||||
|
||||
if ((option_random || first_option < 2) && !option_gametype)
|
||||
;
|
||||
else if (mapheaderinfo[printmap]->typeoflevel & G_TOLFlag(newgametype))
|
||||
{
|
||||
CONS_Printf(" compatible with this gametype\n");
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
|
||||
{
|
||||
newgametype = G_GuessGametypeByTOL(mapheaderinfo[printmap]->typeoflevel);
|
||||
|
||||
if (newgametype == -1)
|
||||
{
|
||||
CONS_Printf(" NOT compatible with any known gametype\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(" NOT compatible with this gametype (try \"%s\" instead)\n", gametypes[newgametype]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf("Invalid map ID %u\n", printmap);
|
||||
}
|
||||
|
||||
Z_Free(realmapname);
|
||||
Z_Free(mapname);
|
||||
}
|
||||
|
||||
static void Command_Maphash_f(void)
|
||||
|
|
|
|||
Loading…
Reference in a new issue