diff --git a/reaction/game/bg_lib.c b/reaction/game/bg_lib.c index f9b09017..68c93385 100644 --- a/reaction/game/bg_lib.c +++ b/reaction/game/bg_lib.c @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.8 2005/09/13 02:33:17 jbravo +// Adding new callvote gametype:map +// // Revision 1.7 2003/09/18 19:26:43 makro // no message // @@ -283,6 +286,51 @@ char *strstr(const char *string, const char *strCharSet) } return (char *) 0; } + +// JBravo: strtok from FreeBSD +char *__strtok_r(char *s, const char *delim, char **last) +{ + char *spanp, *tok; + int c, sc; + + if (s == NULL && (s = *last) == NULL) + return (NULL); + +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { + *last = NULL; + return (NULL); + } + tok = s - 1; + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = '\0'; + *last = s; + return (tok); + } + } while (sc != 0); + } +} + +char *strtok(char *s, const char *delim) +{ + static char *last; + + return (__strtok_r(s, delim, &last)); +} + #endif // bk001211 // bk001120 - presumably needed for Mac @@ -1056,8 +1104,9 @@ double fabs(double x) #define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */ #define FPT 0x00000100 /* floating point number */ -#define to_digit(c) ((c) - '0') -#define is_digit(c) ((unsigned)to_digit(c) <= 9) +// JBravo: moved to bg_lib.h +// #define to_digit(c) ((c) - '0') +// #define is_digit(c) ((unsigned)to_digit(c) <= 9) #define to_char(n) ((n) + '0') void AddInt(char **buf_p, int val, int width, int flags) diff --git a/reaction/game/bg_lib.h b/reaction/game/bg_lib.h index b07cebd4..efaefc2f 100644 --- a/reaction/game/bg_lib.h +++ b/reaction/game/bg_lib.h @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.6 2005/09/13 02:33:17 jbravo +// Adding new callvote gametype:map +// // Revision 1.5 2002/06/16 20:06:14 jbravo // Reindented all the source files with "indent -kr -ut -i8 -l120 -lc120 -sob -bad -bap" // @@ -59,6 +62,7 @@ int strcmp(const char *string1, const char *string2); char *strchr(const char *string, int c); char *strstr(const char *string, const char *strCharSet); char *strncpy(char *strDest, const char *strSource, size_t count); +char *strtok(char *s, const char *delim); int tolower(int c); int toupper(int c); @@ -86,3 +90,7 @@ double tan(double x); int abs(int n); double fabs(double x); double acos(double x); + +// JBravo: moved from bg_lib.c so all can use +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_digit(c) ((c) - '0') diff --git a/reaction/game/g_cmds.c b/reaction/game/g_cmds.c index a321d9be..af0f401e 100644 --- a/reaction/game/g_cmds.c +++ b/reaction/game/g_cmds.c @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.193 2005/09/13 02:33:17 jbravo +// Adding new callvote gametype:map +// // Revision 1.192 2005/09/07 20:27:41 makro // Entity attachment trees // @@ -2024,6 +2027,7 @@ void Cmd_CallVote_f(gentity_t * ent) float delay; char arg1[MAX_STRING_TOKENS]; char arg2[MAX_STRING_TOKENS]; + char *v_gametype, *v_map; gentity_t *kicked; if (!g_allowVote.integer) { @@ -2051,12 +2055,12 @@ void Cmd_CallVote_f(gentity_t * ent) trap_SendServerCommand(ent - g_entities, va("print \"^1You have called the maximum number of votes (%i).\n\"", g_RQ3_maxClientVotes.integer)); return; } -// JBravo: Lets allow spectators to vote in TP + // JBravo: Lets allow spectators to vote in TP if (ent->client->sess.sessionTeam == TEAM_SPECTATOR && g_gametype.integer < GT_TEAM) { trap_SendServerCommand(ent - g_entities, "print \"^1Not allowed to call a vote as spectator.\n\""); return; } - //Slicer Matchmode + //Slicer Matchmode if(g_RQ3_matchmode.integer && ent->client->sess.captain == TEAM_FREE) { trap_SendServerCommand(ent - g_entities, "print \"^1Only team Captains can start a vote.\n\""); return; @@ -2077,49 +2081,49 @@ void Cmd_CallVote_f(gentity_t * ent) } else if (!Q_stricmp(arg1, "g_gametype")) { } else if (!Q_stricmp(arg1, "kick")) { } else if (!Q_stricmp(arg1, "clientkick")) { + // JBravo: adding game, a gametype:map combo + } else if (!Q_stricmp(arg1, "game")) { } else { if(g_RQ3_matchmode.integer) { if (!Q_stricmp(arg1, "resetmatch")) { } else if (!Q_stricmp(arg1, "clearscores")) { } else { trap_SendServerCommand(ent - g_entities, "print \"^1Invalid vote command.\n\""); - trap_SendServerCommand(ent - g_entities,"print \"Valid vote commands are: cyclemap, map , g_gametype , kick , clientkick , clearscores, resetmatch and timelimit .\n\""); + trap_SendServerCommand(ent - g_entities,"print \"Valid vote commands are: cyclemap, map , g_gametype , game , kick , clientkick , clearscores, resetmatch and timelimit .\n\""); return; } } else { trap_SendServerCommand(ent - g_entities, "print \"^1Invalid vote command.\n\""); trap_SendServerCommand(ent - g_entities, - "print \"Valid vote commands are: cyclemap, map , g_gametype , kick , clientkick and timelimit .\n\""); + "print \"Valid vote commands are: cyclemap, map , g_gametype , game , kick , clientkick and timelimit .\n\""); return; } } - // if there is still a vote to be executed - //Makro - commented out - /* - if (level.voteExecuteTime) { - level.voteExecuteTime = 0; - trap_SendConsoleCommand(EXEC_APPEND, va("%s\n", level.voteString)); - } - */ - // special case for g_gametype, check for bad values if (!Q_stricmp(arg1, "g_gametype")) { + // JBravo: Adding the digit check to catch errors + // JBravo: Im cloning this code in the callvote game section. + // Changes here must be done there also. //Makro - added short gametype names - if (!Q_stricmp(arg2, "dm")) { - i = GT_FFA; - } else if (!Q_stricmp(arg2, "tp")) { - i = GT_TEAMPLAY; - } else if (!Q_stricmp(arg2, "tdm")) { - i = GT_TEAM; - } else if (!Q_stricmp(arg2, "ctb")) { - i = GT_CTF; - } else { - //if not a preset name, consider it a number + if (is_digit(arg2[0])) { i = atoi(arg2); + } else { + if (!Q_stricmp(arg2, "dm")) { + i = GT_FFA; + } else if (!Q_stricmp(arg2, "tp")) { + i = GT_TEAMPLAY; + } else if (!Q_stricmp(arg2, "tdm")) { + i = GT_TEAM; + } else if (!Q_stricmp(arg2, "ctb")) { + i = GT_CTF; + } else { + //if not a preset name, consider it an error + i = 999; + } } if (i != GT_FFA && i != GT_TEAMPLAY && i != GT_CTF && i != GT_TEAM) { - trap_SendServerCommand(ent - g_entities, "print \"^1Invalid gametype. Valid gametypes are 0, 3, 4 and 5.\n\""); + trap_SendServerCommand(ent - g_entities, "print \"^1Invalid gametype. Valid gametypes are 0(dm), 3(tdm), 4(tp) and 5(ctb).\n\""); return; } @@ -2143,7 +2147,77 @@ void Cmd_CallVote_f(gentity_t * ent) Com_sprintf(level.voteString, sizeof(level.voteString), "%s", arg1); Com_sprintf(level.voteMap, sizeof(level.voteMap), "%s", arg2); Com_sprintf(level.voteDisplayString, sizeof(level.voteDisplayString), "%s %s", level.voteString, level.voteMap); + } else if (!Q_stricmp(arg1, "game")) { + // JBravo: adding new game vote. Syntax: gametype:map + if (!strchr(arg2, ':')) { + trap_SendServerCommand(ent - g_entities, "print \"^1Invalid vote string. Usage: gametype:map\n\""); + return; + } + v_gametype = strtok(arg2, ":"); + v_map = strtok(NULL, ":"); + + if (is_digit(v_gametype[0])) { + i = atoi(v_gametype); + } else { + if (!Q_stricmp(v_gametype, "dm")) { + i = GT_FFA; + } else if (!Q_stricmp(v_gametype, "tp")) { + i = GT_TEAMPLAY; + } else if (!Q_stricmp(v_gametype, "tdm")) { + i = GT_TEAM; + } else if (!Q_stricmp(v_gametype, "ctb")) { + i = GT_CTF; + } else { + //if not a preset name, consider it an error + i = 999; + } + } + + trap_SendServerCommand(ent - g_entities, va("print \"^1v_map = %s, v_gametype = %s, i = %d\n\"", v_map, v_gametype, i)); + + if (i != GT_FFA && i != GT_TEAMPLAY && i != GT_CTF && i != GT_TEAM) { + trap_SendServerCommand(ent - g_entities, "print \"^1Invalid gametype. Valid gametypes are 0(dm), 3(tdm), 4(tp) and 5(ctb).\n\""); + return; + } + if (!G_FileExists(va("maps/%s.bsp", v_map))) { + trap_SendServerCommand(ent - g_entities, va("print \"^1The map %s does not exist.\n\"", v_map)); + return; + } + + switch (i) { + case GT_FFA: + if (!G_FileSearch(va("scripts/%s.arena", v_map), "rq3dm")) { + trap_SendServerCommand(ent - g_entities, va("print \"^1The map %s does not support DM.\n\"", v_map)); + return; + } + break; + case GT_TEAMPLAY: + if (!G_FileSearch(va("scripts/%s.arena", v_map), "rq3tp")) { + trap_SendServerCommand(ent - g_entities, va("print \"^1The map %s does not support TP.\n\"", v_map)); + return; + } + break; + case GT_TEAM: + if (!G_FileSearch(va("scripts/%s.arena", v_map), "rq3tdm")) { + trap_SendServerCommand(ent - g_entities, va("print \"^1The map %s does not support TDM.\n\"", v_map)); + return; + } + break; + case GT_CTF: + if (!G_FileSearch(va("scripts/%s.arena", v_map), "rq3ctb")) { + trap_SendServerCommand(ent - g_entities, va("print \"^1The map %s does not support CTB.\n\"", v_map)); + return; + } + break; + default: + trap_SendServerCommand(ent - g_entities, "print \"^1Invalid gametype. Valid gametypes are 0(dm), 3(tdm), 4(tp) and 5(ctb).\n\""); + return; + } + Com_sprintf(level.voteString, sizeof(level.voteString), "%s", arg1); + Com_sprintf(level.voteMap, sizeof(level.voteMap), "%s", v_map); + level.voteGametype = i; + Com_sprintf(level.voteDisplayString, sizeof(level.voteDisplayString), "%s on %s", gameNames[i], level.voteMap); } else if (!Q_stricmp(arg1, "cyclemap")) { Com_sprintf(level.voteString, sizeof(level.voteString), "cyclemap"); Com_sprintf(level.voteDisplayString, sizeof(level.voteDisplayString), "%s", level.voteString); diff --git a/reaction/game/g_local.h b/reaction/game/g_local.h index a995b47e..d286fe06 100644 --- a/reaction/game/g_local.h +++ b/reaction/game/g_local.h @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.153 2005/09/13 02:33:17 jbravo +// Adding new callvote gametype:map +// // Revision 1.152 2005/09/07 20:27:41 makro // Entity attachment trees // @@ -905,7 +908,7 @@ typedef struct { char voteDisplayString[MAX_STRING_CHARS]; // vote extras char voteMap[MAX_STRING_CHARS]; - + int voteGametype; // JBravo: For callvote game int voteTime; // level.time vote was called int voteExecuteTime; // time the vote is executed int voteYes; diff --git a/reaction/game/g_main.c b/reaction/game/g_main.c index 2f9de9ad..639f853f 100644 --- a/reaction/game/g_main.c +++ b/reaction/game/g_main.c @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.152 2005/09/13 02:33:17 jbravo +// Adding new callvote gametype:map +// // Revision 1.151 2005/09/07 20:27:42 makro // Entity attachment trees // @@ -2548,12 +2551,13 @@ CheckVote */ void CheckVote(void) { - char userinfo[MAX_INFO_STRING], votestr[MAX_INFO_STRING]; + char userinfo[MAX_INFO_STRING], votestr[MAX_INFO_STRING], gamevotestr[MAX_INFO_STRING]; char *value, *kicked; gentity_t *ent; int kickclient; if (level.voteExecuteTime && level.voteExecuteTime < level.time) { + G_Printf("^1voteString = %s, voteDisplayString = %s\n", level.voteString, level.voteDisplayString); if (g_gametype.integer == GT_TEAMPLAY && level.team_round_going && (Q_stricmp(level.voteString, "map") == 0)) return; @@ -2565,6 +2569,13 @@ void CheckVote(void) trap_Cvar_Set("g_RQ3_ValidIniFile", "2"); // check this later. This trap may not be necessary g_RQ3_ValidIniFile.integer = 2; BeginIntermission(); + } else if (Q_stricmp(level.voteString, "game") == 0) { + trap_Cvar_Set("g_RQ3_ValidIniFile", "2"); + g_RQ3_ValidIniFile.integer = 2; + Com_sprintf(gamevotestr, sizeof(gamevotestr), "%d", level.voteGametype); + Com_sprintf(level.voteString, sizeof(level.voteString), "%s", "map"); + trap_Cvar_Set("g_gametype", gamevotestr); + BeginIntermission(); } else if (Q_stricmp(level.voteString, "g_gametype") == 0) { trap_SendConsoleCommand(EXEC_APPEND, va("%s\n", level.voteString)); trap_SendConsoleCommand(EXEC_APPEND, "map_restart 0\n");