void G_DestroyFireteam(int entityNum) { fireteamData_t *ft; if ((entityNum < 0 || entityNum >= MAX_CLIENTS) || !g_entities[entityNum].client) { G_Error("G_DestroyFireteam: invalid client\n"); } if (!G_IsFireteamLeader(entityNum, &ft)) { G_ClientPrint(entityNum, "You are not the leader of a fireteam\n"); return; } while (ft->joinOrder[0] != -1) { if (ft->joinOrder[0] != entityNum) { #ifdef FEATURE_OMNIBOT Bot_Event_FireTeamDestroyed(ft->joinOrder[0]); #endif trap_SendServerCommand(ft->joinOrder[0], "cpm \"The fireteam you are on has been disbanded\""); } G_RemoveClientFromFireteams(ft->joinOrder[0], qfalse, qfalse); } G_UpdateFireteamConfigString(ft); }
// Should be the only function that ever creates a fireteam void G_RegisterFireteam( /*const char* name,*/ int entityNum ) { fireteamData_t* ft; gentity_t* leader; int count, ident; if ( entityNum < 0 || entityNum >= MAX_CLIENTS ) { G_Error( "G_RegisterFireteam: invalid client" ); } leader = &g_entities[entityNum]; if ( !leader->client ) { G_Error( "G_RegisterFireteam: attempting to register a Fireteam to an entity with no client\n" ); } if ( G_IsOnFireteam( entityNum, NULL ) ) { G_ClientPrintAndReturn( entityNum, "You are already on a fireteam, leave it first" ); } /* if(!name || !*name) { G_ClientPrintAndReturn(entityNum, "You must choose a name for your fireteam"); }*/ if ( ( ft = G_FindFreeFireteam() ) == NULL ) { G_ClientPrintAndReturn( entityNum, "No free fireteams available" ); } if ( leader->client->sess.sessionTeam != TEAM_AXIS && leader->client->sess.sessionTeam != TEAM_ALLIES ) { G_ClientPrintAndReturn( entityNum, "Only players on a team can create a fireteam" ); } count = G_CountTeamFireteams( leader->client->sess.sessionTeam ); if ( count >= MAX_FIRETEAMS / 2 ) { G_ClientPrintAndReturn( entityNum, "Your team already has the maximum number of fireteams allowed" ); } ident = G_FindFreeFireteamIdent( leader->client->sess.sessionTeam ) + 1; if ( ident == 0 ) { G_ClientPrintAndReturn( entityNum, "Um, something is broken, spoink Gordon" ); } // good to go now, i hope! ft->inuse = qtrue; memset( ft->joinOrder, -1, sizeof( level.fireTeams[0].joinOrder ) ); ft->joinOrder[0] = leader - g_entities; ft->ident = ident; if ( g_autoFireteams.integer ) { ft->priv = qfalse; trap_SendServerCommand( entityNum, "aft -1" ); leader->client->pers.autofireteamEndTime = level.time + 20500; } else { ft->priv = qfalse; } // Q_strncpyz(ft->name, name, 32); G_UpdateFireteamConfigString( ft ); }
void G_GiveAdminOfFireTeam(int entityNum, int otherEntityNum) { fireteamData_t *ft, *ft2; char tempArray[MAX_CLIENTS]; int i, x; if (entityNum == otherEntityNum) { return; } if ((entityNum < 0 || entityNum >= MAX_CLIENTS) || !g_entities[entityNum].client) { G_Error("G_KickFireTeamPlayer: invalid client\n"); } if ((otherEntityNum < 0 || otherEntityNum >= MAX_CLIENTS) || !g_entities[otherEntityNum].client) { G_Error("G_KickFireTeamPlayer: invalid client\n"); } if (!G_IsFireteamLeader(entityNum, &ft)) { G_ClientPrint(entityNum, "You must be a fireteam admin to give admin rights to someone else"); return; } if ((!G_IsOnFireteam(otherEntityNum, &ft2)) || ft != ft2) { G_ClientPrint(entityNum, "The other player must be on the same fireteam for you to give admin rights to"); return; } tempArray[0] = otherEntityNum; tempArray[1] = entityNum; x = 2; for (i = 1; i < MAX_FIRETEAM_MEMBERS; i++) { if (ft->joinOrder[i] != otherEntityNum || ft->joinOrder[i] == -1) { tempArray[x++] = ft->joinOrder[i]; continue; } } for (i = 0; i < MAX_FIRETEAM_MEMBERS; i++) { ft->joinOrder[i] = tempArray[i]; } ft->leader = otherEntityNum; G_UpdateFireteamConfigString(ft); G_ClientPrint(otherEntityNum, "You have been given fireteam admin rights"); G_ClientPrint(entityNum, "You have been been stripped of fireteam admin rights"); }
// only way a client should ever join a fireteam, other than creating one void G_AddClientToFireteam(int entityNum, int leaderNum) { fireteamData_t *ft; int i; if ((entityNum < 0 || entityNum >= MAX_CLIENTS) || !g_entities[entityNum].client) { G_Error("G_AddClientToFireteam: invalid client\n"); } if ((leaderNum < 0 || leaderNum >= MAX_CLIENTS) || !g_entities[leaderNum].client) { G_Error("G_AddClientToFireteam: invalid client\n"); } if (g_entities[leaderNum].client->sess.sessionTeam != g_entities[entityNum].client->sess.sessionTeam) { G_ClientPrint(entityNum, "You are not on the same team as that fireteam"); return; } if (!G_IsFireteamLeader(leaderNum, &ft)) { G_ClientPrint(entityNum, "The leader has now left the fireteam you applied to"); return; } if (G_IsOnFireteam(entityNum, NULL)) { G_ClientPrint(entityNum, "You are already on a fireteam"); return; } if (G_CountFireteamMembers(ft) >= MAX_FIRETEAM_MEMBERS) { G_ClientPrint(entityNum, "Too many players already on this fireteam"); return; } for (i = 0; i < MAX_CLIENTS; i++) { if (ft->joinOrder[i] == -1) { // found a free position ft->joinOrder[i] = entityNum; #ifdef FEATURE_OMNIBOT Bot_Event_JoinedFireTeam(entityNum, &g_entities[leaderNum]); #endif G_UpdateFireteamConfigString(ft); return; } } }
// only way a client should ever join a fireteam, other than creating one void G_AddClientToFireteam(int entityNum, int leaderNum) { fireteamData_t *ft; int i; if((entityNum < 0 || entityNum >= MAX_CLIENTS) || !g_entities[entityNum].client) { G_Error("G_AddClientToFireteam: invalid client"); } if((leaderNum < 0 || leaderNum >= MAX_CLIENTS) || !g_entities[leaderNum].client) { G_Error("G_AddClientToFireteam: invalid client"); } if(g_entities[leaderNum].client->sess.sessionTeam != g_entities[entityNum].client->sess.sessionTeam) { G_ClientPrintAndReturn(entityNum, "You are not on the same team as that fireteam"); } if(!G_IsFireteamLeader(leaderNum, &ft)) { G_ClientPrintAndReturn(entityNum, "The leader has now left the Fireteam you applied to"); } if(G_IsOnFireteam(entityNum, NULL)) { G_ClientPrintAndReturn(entityNum, "You are already on a fireteam"); } for(i = 0; i < MAX_CLIENTS; i++) { if(i >= 6) { G_ClientPrintAndReturn(entityNum, "Too many players already on this Fireteam"); return; } if(ft->joinOrder[i] == -1) { // found a free position ft->joinOrder[i] = entityNum; // Omni-bot BEGIN Bot_Event_JoinedFireTeam(entityNum, &g_entities[leaderNum]); // Omni-bot END G_UpdateFireteamConfigString(ft); return; } } }
// The only way a client should be removed from a fireteam void G_RemoveClientFromFireteams( int entityNum, qboolean update, qboolean print ) { fireteamData_t* ft; int i, j; if((entityNum < 0 || entityNum >= MAX_CLIENTS) || !g_entities[entityNum].client) { G_Error("G_RemoveClientFromFireteams: invalid client"); } if(G_IsOnFireteam( entityNum, &ft )) { for(i = 0; i < MAX_CLIENTS; i++) { if(ft->joinOrder[i] == entityNum) { if(i == 0) { if(ft->joinOrder[1] == -1) { ft->inuse = qfalse; ft->ident = -1; } else { // TODO: Inform client of promotion to leader } } for(j = i; j < MAX_CLIENTS-1; j++) { ft->joinOrder[j] = ft->joinOrder[j+1]; } ft->joinOrder[MAX_CLIENTS-1] = -1; break; } } } else { return; } Bot_Event_LeftFireTeam(entityNum); /*if( ft->joinOrder[0] != -1 ) { if( g_entities[(int)ft->joinOrder[0]].r.svFlags & SVF_BOT ) { G_RemoveClientFromFireteams( ft->joinOrder[0], qfalse, qfalse ); } }*/ if( print ) { for( i = 0; i < MAX_CLIENTS; i++ ) { if( ft->joinOrder[i] == -1 ) { break; } trap_SendServerCommand( ft->joinOrder[i], va( "cpm \"%s ^7has left the Fireteam\"\n", level.clients[entityNum].pers.netname ) ); } } if( update ) { G_UpdateFireteamConfigString(ft); } }
/* ================== G_InitWorldSession ================== */ void G_InitWorldSession(void) { char s[MAX_STRING_CHARS]; int i; for (i = 0; i < MAX_FIRETEAMS; ++i) { char *p; int j; trap_Cvar_VariableStringBuffer(va("fireteam%i", i), s, sizeof (s)); p = Info_ValueForKey(s, "id"); j = atoi(p); if (!*p || j == -1) { level.fireTeams[i].inuse = qfalse; } else { level.fireTeams[i].inuse = qtrue; } level.fireTeams[i].ident = j + 1; p = Info_ValueForKey(s, "p"); level.fireTeams[i].priv = !atoi(p) ? qfalse : qtrue; p = Info_ValueForKey(s, "i"); j = 0; if (p && *p) { char *c = p; for (c = strchr(c, ' ') + 1; c && *c; ) { char str[8]; char *l = strchr(c, ' '); if (!l) { break; } Q_strncpyz(str, c, l - c + 1); str[l - c] = '\0'; level.fireTeams[i].joinOrder[j++] = atoi(str); c = l + 1; } } for ( ; j < MAX_CLIENTS; ++j) { level.fireTeams[i].joinOrder[j] = -1; } G_UpdateFireteamConfigString(&level.fireTeams[i]); } }
// The only way a client should be removed from a fireteam void G_RemoveClientFromFireteams(int entityNum, qboolean update, qboolean print) { fireteamData_t *ft; int i, j; if ((entityNum < 0 || entityNum >= MAX_CLIENTS) || !g_entities[entityNum].client) { G_Error("G_RemoveClientFromFireteams: invalid client"); } if (G_IsOnFireteam(entityNum, &ft)) { for (i = 0; i < MAX_CLIENTS; i++) { if (ft->joinOrder[i] == entityNum) { if (i == 0) { if (ft->joinOrder[1] == -1) { ft->inuse = qfalse; ft->ident = -1; } } for (j = i; j < MAX_CLIENTS - 1; j++) { ft->joinOrder[j] = ft->joinOrder[j + 1]; } ft->joinOrder[MAX_CLIENTS - 1] = -1; break; } } } else { return; } if (print) { for (i = 0; i < MAX_CLIENTS; i++) { if (ft->joinOrder[i] == -1) { break; } trap_SendServerCommand(ft->joinOrder[i], va("cpm \"%s has left the Fireteam\"\n", level.clients[entityNum].pers.netname)); } } if (update) { G_UpdateFireteamConfigString(ft); } }
// Should be the only function that ever creates a fireteam void G_RegisterFireteam(int entityNum, qboolean priv) { fireteamData_t *ft; gentity_t *leader; int count, ident; if (entityNum < 0 || entityNum >= MAX_CLIENTS) { G_Error("G_RegisterFireteam: invalid client"); } leader = &g_entities[entityNum]; if (!leader->client) { G_Error("G_RegisterFireteam: attempting to register a Fireteam to an entity with no client\n"); } if (G_IsOnFireteam(entityNum, NULL)) { G_ClientPrintAndReturn(entityNum, "You are already on a fireteam, leave it first"); } if ((ft = G_FindFreeFireteam()) == NULL) { G_ClientPrintAndReturn(entityNum, "No free fireteams available"); } // Nico, allow cross-team fireteams count = G_CountFireteams(); if (count >= MAX_FIRETEAMS) { G_ClientPrintAndReturn(entityNum, "Your team already has the maximum number of fireteams allowed"); } ident = G_FindFreeFireteamIdent() + 1; if (ident == 0) { G_ClientPrintAndReturn(entityNum, "Um, something is broken, spoink Gordon"); } // good to go now, i hope! ft->inuse = qtrue; memset(ft->joinOrder, -1, sizeof (level.fireTeams[0].joinOrder)); ft->joinOrder[0] = leader - g_entities; ft->ident = ident; ft->priv = priv; G_UpdateFireteamConfigString(ft); }
void G_DestroyFireteam( int entityNum ) { fireteamData_t* ft; if ( ( entityNum < 0 || entityNum >= MAX_CLIENTS ) || !g_entities[entityNum].client ) { G_Error( "G_DestroyFireteam: invalid client" ); } if ( !G_IsFireteamLeader( entityNum, &ft ) ) { G_ClientPrintAndReturn( entityNum, "You are not the leader of a fireteam" ); } while ( ft->joinOrder[0] != -1 ) { if ( ft->joinOrder[0] != entityNum ) { trap_SendServerCommand( ft->joinOrder[0], "cpm \"The Fireteam you are on has been disbanded\"\n" ); } G_RemoveClientFromFireteams( ft->joinOrder[0], qfalse, qfalse ); } G_UpdateFireteamConfigString( ft ); }
/* ================== G_InitWorldSession ================== */ void G_InitWorldSession(void) { char s[MAX_STRING_CHARS]; int gt; int i, j; trap_Cvar_VariableStringBuffer("session", s, sizeof(s)); gt = atoi(s); // if the gametype changed since the last session, don't use any // client sessions if (g_gametype.integer != gt) { level.fResetStats = qtrue; G_Printf("Gametype changed, clearing session data.\n"); } else { char *tmp = s; qboolean test = (g_altStopwatchMode.integer != 0 || g_currentRound.integer == 1); #define GETVAL(x) if ((tmp = strchr(tmp, ' ')) == NULL) { return; \ } x = atoi(++tmp); // Get team lock stuff GETVAL(gt); teamInfo[TEAM_AXIS].spec_lock = (gt & TEAM_AXIS) ? qtrue : qfalse; teamInfo[TEAM_ALLIES].spec_lock = (gt & TEAM_ALLIES) ? qtrue : qfalse; // See if we need to clear player stats // FIXME: deal with the multi-map missions if (g_gametype.integer != GT_WOLF_CAMPAIGN) { if ((tmp = strchr(va("%s", tmp), ' ')) != NULL) { tmp++; trap_GetServerinfo(s, sizeof(s)); if (Q_stricmp(tmp, Info_ValueForKey(s, "mapname"))) { level.fResetStats = qtrue; G_Printf("Map changed, clearing player stats.\n"); } } } // have to make sure spec locks follow the right teams if (g_gametype.integer == GT_WOLF_STOPWATCH && g_gamestate.integer != GS_PLAYING && test) { G_swapTeamLocks(); } if (g_swapteams.integer) { G_swapTeamLocks(); } } for (i = 0; i < MAX_FIRETEAMS; i++) { char *p, *c; trap_Cvar_VariableStringBuffer(va("fireteam%i", i), s, sizeof(s)); /* p = Info_ValueForKey( s, "n" ); if(p && *p) { Q_strncpyz( level.fireTeams[i].name, p, 32 ); level.fireTeams[i].inuse = qtrue; } else { *level.fireTeams[i].name = '\0'; level.fireTeams[i].inuse = qfalse; }*/ p = Info_ValueForKey(s, "id"); j = atoi(p); if (!*p || j == -1) { level.fireTeams[i].inuse = qfalse; } else { level.fireTeams[i].inuse = qtrue; } level.fireTeams[i].ident = j + 1; p = Info_ValueForKey(s, "p"); level.fireTeams[i].priv = !atoi(p) ? qfalse : qtrue; p = Info_ValueForKey(s, "i"); j = 0; if (p && *p) { c = p; for (c = strchr(c, ' ') + 1; c && *c; ) { char str[8]; char *l = strchr(c, ' '); if (!l) { break; } Q_strncpyz(str, c, l - c + 1); str[l - c] = '\0'; level.fireTeams[i].joinOrder[j++] = atoi(str); c = l + 1; } } for ( ; j < MAX_CLIENTS; j++) { level.fireTeams[i].joinOrder[j] = -1; } G_UpdateFireteamConfigString(&level.fireTeams[i]); } }
// Command handler void Cmd_FireTeam_MP_f(gentity_t *ent) { char command[32]; int i; if (trap_Argc() < 2) { G_ClientPrint(ent - g_entities, "usage: fireteam <create|leave|apply|invite>"); return; } trap_Argv(1, command, 32); if (!Q_stricmp(command, "create")) { G_RegisterFireteam(ent - g_entities); } else if (!Q_stricmp(command, "disband")) { G_DestroyFireteam(ent - g_entities); } else if (!Q_stricmp(command, "leave")) { G_RemoveClientFromFireteams(ent - g_entities, qtrue, qtrue); } else if (!Q_stricmp(command, "apply")) { char namebuffer[32]; int fireteam; if (trap_Argc() < 3) { G_ClientPrint(ent - g_entities, "usage: fireteam apply <fireteamname|fireteamnumber>"); return; } trap_Argv(2, namebuffer, 32); fireteam = G_FireteamNumberForString(namebuffer, ent->client->sess.sessionTeam); if (fireteam <= 0) { G_ClientPrint(ent - g_entities, "usage: fireteam apply <fireteamname|fireteamnumber>"); return; } G_ApplyToFireTeam(ent - g_entities, fireteam - 1); } else if (!Q_stricmp(command, "invite")) { char namebuffer[32]; int clientnum = 0; if (trap_Argc() < 3) { G_ClientPrint(ent - g_entities, "usage: fireteam invite <clientname|clientnumber>"); return; } trap_Argv(2, namebuffer, 32); for (i = 0; i < MAX_CLIENTS; i++) { if (!g_entities[i].inuse || !g_entities[i].client) { continue; } if (!Q_stricmp(g_entities[i].client->pers.netname, namebuffer)) { clientnum = i + 1; } } if (clientnum <= 0) { clientnum = atoi(namebuffer); if ((clientnum <= 0 || clientnum > MAX_CLIENTS) || !g_entities[clientnum - 1].inuse || !g_entities[clientnum - 1].client) { G_ClientPrint(ent - g_entities, "Invalid client selected"); return; } } if (clientnum <= 0) { G_ClientPrint(ent - g_entities, "usage: fireteam invite <clientname|clientnumber>"); return; } G_InviteToFireTeam(ent - g_entities, clientnum - 1); } else if (!Q_stricmp(command, "warn")) { char namebuffer[32]; int clientnum = 0; if (trap_Argc() < 3) { G_ClientPrint(ent - g_entities, "usage: fireteam warn <clientname|clientnumber>"); return; } trap_Argv(2, namebuffer, 32); for (i = 0; i < MAX_CLIENTS; i++) { if (!g_entities[i].inuse || !g_entities[i].client) { continue; } if (!Q_stricmp(g_entities[i].client->pers.netname, namebuffer)) { clientnum = i + 1; } } if (clientnum <= 0) { clientnum = atoi(namebuffer); if ((clientnum <= 0 || clientnum > MAX_CLIENTS) || !g_entities[clientnum - 1].inuse || !g_entities[clientnum - 1].client) { G_ClientPrint(ent - g_entities, "Invalid client selected"); return; } } if (clientnum <= 0) { G_ClientPrint(ent - g_entities, "usage: fireteam warn <clientname|clientnumber>"); return; } G_WarnFireTeamPlayer(ent - g_entities, clientnum - 1); } else if (!Q_stricmp(command, "kick")) { char namebuffer[32]; int clientnum = 0; if (trap_Argc() < 3) { G_ClientPrint(ent - g_entities, "usage: fireteam kick <clientname|clientnumber>"); return; } trap_Argv(2, namebuffer, 32); for (i = 0; i < MAX_CLIENTS; i++) { if (!g_entities[i].inuse || !g_entities[i].client) { continue; } if (!Q_stricmp(g_entities[i].client->pers.netname, namebuffer)) { clientnum = i + 1; } } if (clientnum <= 0) { clientnum = atoi(namebuffer); if ((clientnum <= 0 || clientnum > MAX_CLIENTS) || !g_entities[clientnum - 1].inuse || !g_entities[clientnum - 1].client) { G_ClientPrint(ent - g_entities, "Invalid client selected"); return; } } if (clientnum <= 0) { G_ClientPrint(ent - g_entities, "usage: fireteam kick <clientname|clientnumber>"); return; } G_KickFireTeamPlayer(ent - g_entities, clientnum - 1); } else if (!Q_stricmp(command, "propose")) { char namebuffer[32]; int clientnum = 0; if (trap_Argc() < 3) { G_ClientPrint(ent - g_entities, "usage: fireteam propose <clientname|clientnumber>"); return; } trap_Argv(2, namebuffer, 32); for (i = 0; i < MAX_CLIENTS; i++) { if (!g_entities[i].inuse || !g_entities[i].client) { continue; } if (!Q_stricmp(g_entities[i].client->pers.netname, namebuffer)) { clientnum = i + 1; } } if (clientnum <= 0) { clientnum = atoi(namebuffer); if ((clientnum <= 0 || clientnum > MAX_CLIENTS) || !g_entities[clientnum - 1].inuse || !g_entities[clientnum - 1].client) { G_ClientPrint(ent - g_entities, "Invalid client selected"); return; } } if (clientnum <= 0) { G_ClientPrint(ent - g_entities, "usage: fireteam propose <clientname|clientnumber>"); return; } G_ProposeFireTeamPlayer(ent - g_entities, clientnum - 1); } else if (!Q_stricmp(command, "privacy")) { fireteamData_t *ft; if (G_IsFireteamLeader(ent - g_entities, &ft)) { if (ft->priv) { ft->priv = qfalse; G_UpdateFireteamConfigString(ft); G_ClientPrint(ent - g_entities, "Your fireteam is now public"); return; } else { ft->priv = qtrue; G_UpdateFireteamConfigString(ft); G_ClientPrint(ent - g_entities, "Your fireteam is now private"); return; } } else { G_ClientPrint(ent - g_entities, "You are not a fireteam admin"); return; } } else if (!Q_stricmp(command, "admin")) { char namebuffer[32]; int clientnum = 0; if (trap_Argc() < 3) { G_ClientPrint(ent - g_entities, "usage: fireteam admin <clientname|clientnumber>"); return; } trap_Argv(2, namebuffer, 32); for (i = 0; i < MAX_CLIENTS; i++) { if (!g_entities[i].inuse || !g_entities[i].client) { continue; } if (!Q_stricmp(g_entities[i].client->pers.netname, namebuffer)) { clientnum = i + 1; } } if (clientnum <= 0) { clientnum = atoi(namebuffer); if ((clientnum <= 0 || clientnum > MAX_CLIENTS) || !g_entities[clientnum - 1].inuse || !g_entities[clientnum - 1].client) { G_ClientPrint(ent - g_entities, "Invalid client selected"); return; } } if (clientnum <= 0) { G_ClientPrint(ent - g_entities, "usage: fireteam admin <clientname|clientnumber>"); return; } G_GiveAdminOfFireTeam(ent - g_entities, clientnum - 1); } }
// The only way a client should be removed from a fireteam void G_RemoveClientFromFireteams(int entityNum, qboolean update, qboolean print) { fireteamData_t *ft; int i; if ((entityNum < 0 || entityNum >= MAX_CLIENTS) || !g_entities[entityNum].client) { G_Error("G_RemoveClientFromFireteams: invalid client\n"); } if (G_IsOnFireteam(entityNum, &ft)) { int j, firstHuman; for (i = 0; i < MAX_FIRETEAM_MEMBERS && i < g_maxclients.integer; ++i) { if (ft->joinOrder[i] == entityNum) { if (i == 0) { if (ft->joinOrder[1] == -1) { ft->inuse = qfalse; ft->ident = -1; } else { // disband the fireteam if only bots left in if (G_OnlyBotsInFireteam(ft, entityNum, &firstHuman)) { // empty the fireteam for (j = 0; j < g_maxclients.integer - 1; j++) { #ifdef FEATURE_OMNIBOT Bot_Event_LeftFireTeam(ft->joinOrder[j]); #endif ft->joinOrder[j] = -1; } ft->inuse = qfalse; ft->ident = -1; G_UpdateFireteamConfigString(ft); return; } else { // try to pick a bot as fireteam leader if (g_entities[(int)(ft->joinOrder[1])].r.svFlags & SVF_BOT) { if (firstHuman != -1) { // swap first human with first bot int tmp = ft->joinOrder[1]; ft->joinOrder[1] = ft->joinOrder[firstHuman]; ft->joinOrder[firstHuman] = tmp; } } else { firstHuman = 1; } // inform client of promotion to leader if (firstHuman != -1) { trap_SendServerCommand(ft->joinOrder[firstHuman], "cpm \"You are now the leader of your fireteam\""); } } } } for (j = i; j < g_maxclients.integer - 1; j++) { ft->joinOrder[j] = ft->joinOrder[j + 1]; } ft->joinOrder[g_maxclients.integer - 1] = -1; break; } } } else { return; } #ifdef FEATURE_OMNIBOT Bot_Event_LeftFireTeam(entityNum); #endif if (print) { for (i = 0; i < MAX_CLIENTS; i++) { if (ft->joinOrder[i] == -1) { break; } trap_SendServerCommand(ft->joinOrder[i], va("cpm \"%s ^7has left the fireteam\"", level.clients[entityNum].pers.netname)); } } if (update) { G_UpdateFireteamConfigString(ft); } }
// Should be the only function that ever creates a fireteam void G_RegisterFireteam(int entityNum) { fireteamData_t *ft; gentity_t *leader; int count, ident; if (entityNum < 0 || entityNum >= MAX_CLIENTS) { G_Error("G_RegisterFireteam: invalid client\n"); } leader = &g_entities[entityNum]; if (!leader->client) { G_Error("G_RegisterFireteam: attempting to register a fireteam to an entity with no client\n"); } if (G_IsOnFireteam(entityNum, NULL)) { G_ClientPrint(entityNum, "You are already on a fireteam, leave it first"); return; } if ((ft = G_FindFreeFireteam()) == NULL) { G_ClientPrint(entityNum, "No free fireteams available"); return; } if (leader->client->sess.sessionTeam != TEAM_AXIS && leader->client->sess.sessionTeam != TEAM_ALLIES) { G_ClientPrint(entityNum, "Only players on a team can create a fireteam"); return; } count = G_CountTeamFireteams(leader->client->sess.sessionTeam); if (count >= MAX_FIRETEAMS / 2) { G_ClientPrint(entityNum, "Your team already has the maximum number of fireteams allowed"); return; } ident = G_FindFreeFireteamIdent(leader->client->sess.sessionTeam) + 1; if (ident == 0) { G_Error("G_RegisterFireteam: free fireteam is invalid\n"); return; } // good to go now ft->inuse = qtrue; memset(ft->joinOrder, -1, sizeof(level.fireTeams[0].joinOrder)); ft->joinOrder[0] = leader - g_entities; ft->ident = ident; if (g_autoFireteams.integer) { ft->priv = qfalse; trap_SendServerCommand(entityNum, "aft -1"); leader->client->pers.autofireteamEndTime = level.time + 20500; } else { ft->priv = qfalse; } #ifdef FEATURE_OMNIBOT Bot_Event_FireTeamCreated(entityNum, ft->ident); Bot_Event_JoinedFireTeam(leader - g_entities, leader); #endif G_UpdateFireteamConfigString(ft); }