diff --git a/code/game/ai_dmq3.c b/code/game/ai_dmq3.c index 5198cb3d..6e796656 100644 --- a/code/game/ai_dmq3.c +++ b/code/game/ai_dmq3.c @@ -5218,7 +5218,7 @@ BotDeathmatchAI ================== */ void BotDeathmatchAI(bot_state_t *bs, float thinktime) { - char gender[144], name[144], buf[144]; + char gender[144], name[144]; char userinfo[MAX_INFO_STRING]; int i; @@ -5232,11 +5232,6 @@ void BotDeathmatchAI(bot_state_t *bs, float thinktime) { trap_GetUserinfo(bs->client, userinfo, sizeof(userinfo)); Info_SetValueForKey(userinfo, "sex", gender); trap_SetUserinfo(bs->client, userinfo); - //set the team - if ( !bs->map_restart && g_gametype.integer != GT_TOURNAMENT ) { - Com_sprintf(buf, sizeof(buf), "team %s", bs->settings.team); - trap_EA_Command(bs->client, buf); - } //set the chat gender if (gender[0] == 'm') trap_BotSetChatGender(bs->cs, CHAT_GENDERMALE); else if (gender[0] == 'f') trap_BotSetChatGender(bs->cs, CHAT_GENDERFEMALE); diff --git a/code/game/g_bot.c b/code/game/g_bot.c index 6cc39178..c509772b 100644 --- a/code/game/g_bot.c +++ b/code/game/g_bot.c @@ -542,7 +542,6 @@ qboolean G_BotConnect( int clientNum, qboolean restart ) { Q_strncpyz( settings.characterfile, Info_ValueForKey( userinfo, "characterfile" ), sizeof(settings.characterfile) ); settings.skill = atof( Info_ValueForKey( userinfo, "skill" ) ); - Q_strncpyz( settings.team, Info_ValueForKey( userinfo, "team" ), sizeof(settings.team) ); if (!BotAISetupClient( clientNum, &settings, restart )) { trap_DropClient( clientNum, "BotAISetupClient failed" ); @@ -670,7 +669,7 @@ static void G_AddBot( const char *name, float skill, const char *team, int delay team = "red"; } } - Info_SetValueForKey( userinfo, "team", team ); + Info_SetValueForKey( userinfo, "teampref", team ); // register the userinfo trap_SetUserinfo( clientNum, userinfo ); diff --git a/code/game/g_client.c b/code/game/g_client.c index d1dcbc3c..89f20982 100644 --- a/code/game/g_client.c +++ b/code/game/g_client.c @@ -702,7 +702,7 @@ if desired. */ void ClientUserinfoChanged( int clientNum ) { gentity_t *ent; - int teamTask, teamLeader, team, health; + int teamTask, teamLeader, health; char *s; char model[MAX_QPATH]; char headModel[MAX_QPATH]; @@ -726,12 +726,6 @@ void ClientUserinfoChanged( int clientNum ) { trap_DropClient(clientNum, "Invalid userinfo"); } - // check for local client - s = Info_ValueForKey( userinfo, "ip" ); - if ( !strcmp( s, "localhost" ) ) { - client->pers.localClient = qtrue; - } - // check the item prediction s = Info_ValueForKey( userinfo, "cg_predictItems" ); if ( !atoi( s ) ) { @@ -787,22 +781,6 @@ void ClientUserinfoChanged( int clientNum ) { Q_strncpyz( headModel, Info_ValueForKey (userinfo, "headmodel"), sizeof( headModel ) ); } - // bots set their team a few frames later - if (g_gametype.integer >= GT_TEAM && g_entities[clientNum].r.svFlags & SVF_BOT) { - s = Info_ValueForKey( userinfo, "team" ); - if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) { - team = TEAM_RED; - } else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) { - team = TEAM_BLUE; - } else { - // pick the team with the least number of players - team = PickTeam( clientNum ); - } - } - else { - team = client->sess.sessionTeam; - } - /* NOTE: all client side now // team @@ -871,7 +849,7 @@ void ClientUserinfoChanged( int clientNum ) { if (ent->r.svFlags & SVF_BOT) { s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d", - client->pers.netname, team, model, headModel, c1, c2, + client->pers.netname, client->sess.sessionTeam, model, headModel, c1, c2, client->pers.maxHealth, client->sess.wins, client->sess.losses, Info_ValueForKey( userinfo, "skill" ), teamTask, teamLeader ); } @@ -956,11 +934,11 @@ char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot ) { client->pers.connected = CON_CONNECTING; - // read or initialize the session data - if ( firstTime || level.newSession ) { - G_InitSessionData( client, userinfo ); + // check for local client + value = Info_ValueForKey( userinfo, "ip" ); + if ( !strcmp( value, "localhost" ) ) { + client->pers.localClient = qtrue; } - G_ReadSessionData( client ); if( isBot ) { ent->r.svFlags |= SVF_BOT; @@ -970,6 +948,12 @@ char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot ) { } } + // read or initialize the session data + if ( firstTime || level.newSession ) { + G_InitSessionData( client, userinfo ); + } + G_ReadSessionData( client ); + // get and distribute relevent paramters G_LogPrintf( "ClientConnect: %i\n", clientNum ); ClientUserinfoChanged( clientNum ); diff --git a/code/game/g_cmds.c b/code/game/g_cmds.c index 7606edbe..46a69ca8 100644 --- a/code/game/g_cmds.c +++ b/code/game/g_cmds.c @@ -512,7 +512,7 @@ void BroadcastTeamChange( gclient_t *client, int oldTeam ) SetTeam ================= */ -void SetTeam( gentity_t *ent, char *s ) { +void SetTeam( gentity_t *ent, const char *s ) { int team, oldTeam; gclient_t *client; int clientNum; @@ -554,7 +554,7 @@ void SetTeam( gentity_t *ent, char *s ) { team = PickTeam( clientNum ); } - if ( g_teamForceBalance.integer ) { + if ( g_teamForceBalance.integer && !client->pers.localClient && !( ent->r.svFlags & SVF_BOT ) ) { int counts[TEAM_NUM_TEAMS]; counts[TEAM_BLUE] = TeamCount( clientNum, TEAM_BLUE ); @@ -642,7 +642,7 @@ void SetTeam( gentity_t *ent, char *s ) { // get and distribute relevent paramters ClientUserinfoChanged( clientNum ); - // client hasn't spawned yet, they sent an early team command + // client hasn't spawned yet, they sent an early team command, teampref userinfo, or g_teamAutoJoin is enabled if ( client->pers.connected != CON_CONNECTED ) { return; } diff --git a/code/game/g_local.h b/code/game/g_local.h index d2ff996c..ebac56c6 100644 --- a/code/game/g_local.h +++ b/code/game/g_local.h @@ -427,7 +427,7 @@ char *G_NewString( const char *string ); void Cmd_Score_f (gentity_t *ent); void StopFollowing( gentity_t *ent ); void BroadcastTeamChange( gclient_t *client, int oldTeam ); -void SetTeam( gentity_t *ent, char *s ); +void SetTeam( gentity_t *ent, const char *s ); void Cmd_FollowCycle_f( gentity_t *ent, int dir ); // @@ -676,7 +676,6 @@ typedef struct bot_settings_s { char characterfile[MAX_FILEPATH]; float skill; - char team[MAX_FILEPATH]; } bot_settings_t; int BotAISetup( int restart ); @@ -745,6 +744,7 @@ extern vmCvar_t g_enableDust; extern vmCvar_t g_enableBreath; extern vmCvar_t g_singlePlayer; extern vmCvar_t g_proxMineTimeout; +extern vmCvar_t g_localTeamPref; void trap_Print( const char *text ); void trap_Error( const char *text ) __attribute__((noreturn)); diff --git a/code/game/g_main.c b/code/game/g_main.c index 09287623..fb32be92 100644 --- a/code/game/g_main.c +++ b/code/game/g_main.c @@ -81,6 +81,7 @@ vmCvar_t pmove_fixed; vmCvar_t pmove_msec; vmCvar_t g_rankings; vmCvar_t g_listEntity; +vmCvar_t g_localTeamPref; #ifdef MISSIONPACK vmCvar_t g_obeliskHealth; vmCvar_t g_obeliskRegenPeriod; @@ -176,7 +177,8 @@ static cvarTable_t gameCvarTable[] = { { &pmove_fixed, "pmove_fixed", "0", CVAR_SYSTEMINFO, 0, qfalse}, { &pmove_msec, "pmove_msec", "8", CVAR_SYSTEMINFO, 0, qfalse}, - { &g_rankings, "g_rankings", "0", 0, 0, qfalse} + { &g_rankings, "g_rankings", "0", 0, 0, qfalse}, + { &g_localTeamPref, "g_localTeamPref", "", 0, 0, qfalse } }; diff --git a/code/game/g_session.c b/code/game/g_session.c index eaac1a71..6f97ba99 100644 --- a/code/game/g_session.c +++ b/code/game/g_session.c @@ -105,17 +105,27 @@ void G_InitSessionData( gclient_t *client, char *userinfo ) { sess = &client->sess; + // check for team preference, mainly for bots + value = Info_ValueForKey( userinfo, "teampref" ); + + // check for human's team preference set by start server menu + if ( !value[0] && g_localTeamPref.string[0] && client->pers.localClient ) { + value = g_localTeamPref.string; + + // clear team so it's only used once + trap_Cvar_Set( "g_localTeamPref", "" ); + } + // initial team determination if ( g_gametype.integer >= GT_TEAM ) { - if ( g_teamAutoJoin.integer && !(g_entities[ client - level.clients ].r.svFlags & SVF_BOT) ) { - sess->sessionTeam = PickTeam( -1 ); - BroadcastTeamChange( client, -1 ); - } else { - // always spawn as spectator in team games - sess->sessionTeam = TEAM_SPECTATOR; + // always spawn as spectator in team games + sess->sessionTeam = TEAM_SPECTATOR; + sess->spectatorState = SPECTATOR_FREE; + + if ( value[0] || g_teamAutoJoin.integer ) { + SetTeam( &g_entities[client - level.clients], value ); } } else { - value = Info_ValueForKey( userinfo, "team" ); if ( value[0] == 's' ) { // a willing spectator, not a waiting-in-line sess->sessionTeam = TEAM_SPECTATOR; @@ -141,9 +151,10 @@ void G_InitSessionData( gclient_t *client, char *userinfo ) { break; } } + + sess->spectatorState = SPECTATOR_FREE; } - sess->spectatorState = SPECTATOR_FREE; AddTournamentQueue(client); G_WriteClientSessionData( client ); diff --git a/code/q3_ui/ui_main.c b/code/q3_ui/ui_main.c index bd9359a0..216269cf 100644 --- a/code/q3_ui/ui_main.c +++ b/code/q3_ui/ui_main.c @@ -214,7 +214,8 @@ static cvarTable_t cvarTable[] = { { &ui_server16, "server16", "", CVAR_ARCHIVE }, { &ui_cdkeychecked, "ui_cdkeychecked", "0", CVAR_ROM }, - { &ui_ioq3, "ui_ioq3", "1", CVAR_ROM } + { &ui_ioq3, "ui_ioq3", "1", CVAR_ROM }, + { NULL, "g_localTeamPref", "", 0 } }; static int cvarTableSize = ARRAY_LEN( cvarTable ); @@ -244,6 +245,10 @@ void UI_UpdateCvars( void ) { cvarTable_t *cv; for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) { + if ( !cv->vmCvar ) { + continue; + } + trap_Cvar_Update( cv->vmCvar ); } } diff --git a/code/q3_ui/ui_startserver.c b/code/q3_ui/ui_startserver.c index 82865ad5..b4883d4d 100644 --- a/code/q3_ui/ui_startserver.c +++ b/code/q3_ui/ui_startserver.c @@ -815,7 +815,11 @@ static void ServerOptions_Start( void ) { // set player's team if( dedicated == 0 && s_serveroptions.gametype >= GT_TEAM ) { + // send team command for vanilla q3 game qvm trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait 5; team %s\n", playerTeam_list[s_serveroptions.playerTeam[0].curvalue] ) ); + + // set g_localTeamPref for ioq3 game qvm + trap_Cvar_Set( "g_localTeamPref", playerTeam_list[s_serveroptions.playerTeam[0].curvalue] ); } } diff --git a/code/ui/ui_main.c b/code/ui/ui_main.c index 60170614..36604705 100644 --- a/code/ui/ui_main.c +++ b/code/ui/ui_main.c @@ -3026,7 +3026,11 @@ static void UI_StartSkirmish(qboolean next) { } } if (g >= GT_TEAM ) { + // send team command for vanilla q3 game qvm trap_Cmd_ExecuteText( EXEC_APPEND, "wait 5; team Red\n" ); + + // set g_localTeamPref for ioq3 game qvm + trap_Cvar_Set( "g_localTeamPref", "Red" ); } } @@ -5849,6 +5853,7 @@ static cvarTable_t cvarTable[] = { { &ui_realCaptureLimit, "capturelimit", "8", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART}, { &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE}, + { NULL, "g_localTeamPref", "", 0 }, }; static int cvarTableSize = ARRAY_LEN( cvarTable ); @@ -5878,6 +5883,10 @@ void UI_UpdateCvars( void ) { cvarTable_t *cv; for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) { + if ( !cv->vmCvar ) { + continue; + } + trap_Cvar_Update( cv->vmCvar ); } }