diff --git a/code/game/g_admin.c b/code/game/g_admin.c index e01fc66a..243be209 100644 --- a/code/game/g_admin.c +++ b/code/game/g_admin.c @@ -194,6 +194,12 @@ g_admin_cmd_t g_admin_cmds[ ] = { "display a (partial) list of active bans", "(^5start at ban#^7) (^5name|IP^7)" }, + //KK-OAX + { + "shuffle", G_admin_shuffle, "f", + "Shuffles the teams" + "" + }, { "slap", G_admin_slap, "S", "Reduces the health of the selected player by the damage specified", @@ -3111,6 +3117,13 @@ qboolean G_admin_warn( gentity_t *ent, int skiparg ) } } +qboolean G_admin_shuffle( gentity_t *ent, int skipargs ) +{ + trap_SendConsoleCommand( EXEC_APPEND, "shuffle" ); + AP( va( "print \"^3!shuffle: ^7teams shuffled by %s \n\"", + ( ent ) ? ent->client->pers.netname : "console" ) ); + return qtrue; +} //KK-OAX End Additions diff --git a/code/game/g_admin.h b/code/game/g_admin.h index 72a77fe4..9eb3d1b5 100644 --- a/code/game/g_admin.h +++ b/code/game/g_admin.h @@ -187,6 +187,7 @@ qboolean G_admin_disorient(gentity_t *ent, int skiparg); qboolean G_admin_orient(gentity_t *ent, int skiparg); qboolean G_admin_slap(gentity_t *ent, int skiparg); qboolean G_admin_warn(gentity_t *ent, int skiparg); +qboolean G_admin_shuffle(gentity_t *ent, int skiparg); void G_admin_print(gentity_t *ent, char *m); void G_admin_buffer_print(gentity_t *ent, char *m); diff --git a/code/game/g_local.h b/code/game/g_local.h index 8a149374..64aa824d 100644 --- a/code/game/g_local.h +++ b/code/game/g_local.h @@ -898,6 +898,7 @@ void G_RunClient( gentity_t *ent ); qboolean OnSameTeam( const gentity_t *ent1, const gentity_t *ent2 ); void Team_CheckDroppedItem( const gentity_t *dropped ); qboolean CheckObeliskAttack( const gentity_t *obelisk, const gentity_t *attacker ); +void ShuffleTeams(void); //KK-OAX Added for Command Handling Changes (r24) team_t G_TeamFromString( char *str ); /** diff --git a/code/game/g_main.c b/code/game/g_main.c index 9ff546b5..90a5dc7a 100644 --- a/code/game/g_main.c +++ b/code/game/g_main.c @@ -652,6 +652,9 @@ void G_UpdateCvars( void ) if( allowedVote("clientkick") ) voteflags|=VF_clientkick; + if( allowedVote("shuffle") ) + voteflags|=VF_shuffle; + if( allowedVote("nextmap") ) voteflags|=VF_nextmap; diff --git a/code/game/g_svcmds.c b/code/game/g_svcmds.c index 0c8d959c..c5434084 100644 --- a/code/game/g_svcmds.c +++ b/code/game/g_svcmds.c @@ -493,6 +493,8 @@ struct { { "say_team", qtrue, Svcmd_TeamMessage_f }, { "say", qtrue, Svcmd_MessageWrapper }, { "chat", qtrue, Svcmd_Chat_f }, + //Shuffle the teams + { "shuffle", qfalse, ShuffleTeams }, //Kicks a player by number in the game logic rather than the server number { "clientkick_game", qfalse, ClientKick_f }, { "endgamenow", qfalse, EndGame_f }, diff --git a/code/game/g_team.c b/code/game/g_team.c index 6ba24203..92de538c 100644 --- a/code/game/g_team.c +++ b/code/game/g_team.c @@ -2406,3 +2406,52 @@ qboolean CheckObeliskAttack( const gentity_t *obelisk, const gentity_t *attacker return qfalse; } +/* +================ +ShuffleTeams + *Randomizes the teams based on a type of function and then restarts the map + *Currently there is only one type so type is ignored. You can add total randomizaion or waighted randomization later. + * + *The function will split the teams like this: + *1. Red team + *2. Blue team + *3. Blue team + *4. Red team + *5. Go to 1 +================ +*/ +void ShuffleTeams(void) +{ + int i; + int nextTeam = TEAM_RED; + int count = 0; + + if (!G_IsATeamGametype(g_gametype.integer)) { + return; + } + + for (i = 0; i < level.numConnectedClients; i++) { + gclient_t *cl; + cl = &level.clients[level.sortedClients[i]]; + + if (g_entities[cl - level.clients].r.svFlags & SVF_BOT) { + continue; + } + + if (cl->sess.sessionTeam == TEAM_RED || cl->sess.sessionTeam == TEAM_BLUE) { + cl->sess.sessionTeam = nextTeam; + count++; + G_Printf("%i\n", nextTeam); + if (nextTeam == TEAM_RED) { + nextTeam = TEAM_BLUE; + } else if (nextTeam == TEAM_BLUE) { + nextTeam = TEAM_RED; + } + + ClientUserinfoChanged(cl - level.clients); + ClientBegin(cl - level.clients); + } + } + + trap_SendConsoleCommand(EXEC_APPEND, "map_restart 0\n"); +} diff --git a/code/q3_ui/ui_votemenu.c b/code/q3_ui/ui_votemenu.c index d8c7d3dc..63cfd982 100644 --- a/code/q3_ui/ui_votemenu.c +++ b/code/q3_ui/ui_votemenu.c @@ -48,6 +48,7 @@ static char* votemenu_artlist[] = #define ID_TIME 108 #define ID_GAMETYPE 109 #define ID_CUSTOM 110 +#define ID_SHUFFLE 111 #define ID_YES 112 #define ID_NO 113 @@ -68,6 +69,7 @@ typedef struct qboolean fraglimit; qboolean timelimit; qboolean custom; + qboolean shuffle; } votemenu_logic_t; static votemenu_logic_t s_votemenu_logic; @@ -85,6 +87,7 @@ typedef struct static ui_menuitem_t s_items[] = { {ID_NEXTMAP, "Next map", &s_votemenu_logic.nextmap}, {ID_RESTART, "Restart match", &s_votemenu_logic.map_restart}, + {ID_SHUFFLE,"Shuffle teams", &s_votemenu_logic.shuffle}, {ID_MAP,"Change map", &s_votemenu_logic.map}, {ID_GAMETYPE,"Change gametype", &s_votemenu_logic.gametype}, {ID_KICK,"Kick player", &s_votemenu_logic.clientkick}, @@ -130,6 +133,7 @@ static void VoteMenu_CheckVoteNames( void ) { s_votemenu_logic.timelimit = voteflags&VF_timelimit; s_votemenu_logic.fraglimit = voteflags&VF_fraglimit; s_votemenu_logic.custom = voteflags&VF_custom; + s_votemenu_logic.shuffle = voteflags&VF_shuffle; } /* @@ -165,6 +169,10 @@ static void VoteMenu_Event( void* ptr, int event ) trap_Cmd_ExecuteText( EXEC_APPEND, "callvote g_doWarmup 1" ); UI_PopMenu(); break; + case ID_SHUFFLE: + trap_Cmd_ExecuteText( EXEC_APPEND, "callvote shuffle" ); + UI_PopMenu(); + break; case ID_FRAG: UI_VoteFraglimitMenu(); //Don't pop! It will do a double pop if successfull