[code] Class Limitation


(Azyu) #1

This is a code of Class Limitation features.
Here we go!

find in g_locals.h:

extern vmCvar_t      g_disableComplaints; 

below add:

extern vmCvar_t      team_maxMedics;   // Medics 
extern vmCvar_t      team_maxEngineers;   // Engineers 
extern vmCvar_t      team_maxFieldOps;   // Field Ops 
extern vmCvar_t      team_maxCovertOps;   // Covert Ops 

find in g_main.c:

vmCvar_t      g_disableComplaints; 

below add:

vmCvar_t      team_maxMedics; 
vmCvar_t      team_maxEngineers; 
vmCvar_t      team_maxFieldOps; 
vmCvar_t      team_maxCovertOps; 

find in g_main.c:

{ &g_disableComplaints, "g_disableComplaints", "0", CVAR_ARCHIVE },

below add:

{ &team_maxMedics, "team_maxMedics", "-1", CVAR_ARCHIVE },
{ &team_maxEngineers, "team_maxEngineers", "-1", CVAR_ARCHIVE },
{ &team_maxFieldOps, "team_maxFieldOps", "-1", CVAR_ARCHIVE },
{ &team_maxCovertOps, "team_maxCovertOps", "-1", CVAR_ARCHIVE },

find in g_cmds.c, and replace this code

// Azyu - Class Limitation
int G_ClassCount( gentity_t* ent, int playerType ) { 
   int i, j, cnt=0; 

   if( playerType < PC_SOLDIER || playerType > PC_COVERTOPS ) 
      return 0; 

   for( i = 0; i < level.numConnectedClients; i++ ) { 
      j = level.sortedClients[i]; 
       
      if( j == ent-g_entities ) { 
         continue; 
      } 

      if( level.clients[j].sess.sessionTeam != ent->client->sess.sessionTeam ) { 
         continue; 
      } 

      if( level.clients[j].sess.playerType != playerType && level.clients[j].sess.latchPlayerType != playerType ) { 
         continue; 
      } 

      cnt++; 
   } 

   return cnt; 
} 

void Cmd_Team_f( gentity_t *ent, unsigned int dwCommand, qboolean fValue ) { 
   char      s[MAX_TOKEN_CHARS]; 
   char      ptype[4]; 
   char      weap[4], weap2[4]; 
   int         playerType, count; 
   weapon_t   w, w2; 
   qboolean   limit = qfalse; 

   if ( trap_Argc() < 2 ) { 
      char *pszTeamName; 

      switch ( ent->client->sess.sessionTeam ) { 
         case TEAM_ALLIES: 
            pszTeamName = "Allies"; 
            break; 
         case TEAM_AXIS: 
            pszTeamName = "Axis"; 
            break; 
         case TEAM_SPECTATOR: 
            pszTeamName = "Spectator"; 
            break; 
         case TEAM_FREE: 
         default: 
            pszTeamName = "Free"; 
            break; 
      } 

      CP(va("print \"%s team
\"", pszTeamName)); 
      return; 
   } 

   trap_Argv( 1, s,      sizeof( s      )); 
   trap_Argv( 2, ptype,   sizeof( ptype   )); 
   trap_Argv( 3, weap,      sizeof( weap   )); 
   trap_Argv( 4, weap2,   sizeof( weap2   )); 

   w =      atoi( weap ); 
   w2 =   atoi( weap2 ); 

   playerType = ent->client->sess.latchPlayerType = atoi( ptype ); 

   count = G_ClassCount( ent, playerType ); 
    
   switch( playerType ) { 
   case PC_MEDIC: 
      if( team_maxMedics.integer == -1 ) break; 
      if( count >= team_maxMedics.integer ) 
      { 
         CP( "cp \"^1Medic^7 is not available! Choose another class!
\"" ); 
         limit = qtrue; 
      } 
      break; 
   case PC_ENGINEER: 
      if( team_maxEngineers.integer == -1 ) break; 
      if( count >= team_maxEngineers.integer ) 
      { 
         CP( "cp \"^1Engineer^7 is not available! Choose another class!
\"" ); 
         limit = qtrue; 
      } 
      break; 
   case PC_FIELDOPS: 
      if( team_maxFieldOps.integer == -1 ) break; 
      if( count >= team_maxFieldOps.integer ) 
      { 
         CP( "cp \"^1Field Ops^7 is not available! Choose another class!
\"" ); 
         limit = qtrue; 
      } 
      break; 
   case PC_COVERTOPS: 
      if( team_maxFieldOps.integer == -1 ) break; 
      if( count >= team_maxFieldOps.integer ) 
      { 
         CP( "cp \"^1Covert Ops^7 is not available! Choose another class!
\"" ); 
         limit = qtrue; 
      } 
      break; 
   } 

   if( limit ) 
   { 
      ent->client->sess.latchPlayerType = PC_SOLDIER; 
      w = (ent->client->sess.sessionTeam == TEAM_AXIS) ? WP_MP40 : WP_THOMPSON; 
      w2 = (ent->client->sess.sessionTeam == TEAM_AXIS) ? WP_LUGER : WP_COLT; 
   } 

   if( ent->client->sess.latchPlayerType < PC_SOLDIER || ent->client->sess.latchPlayerType > PC_COVERTOPS ) { 
      ent->client->sess.latchPlayerType = PC_SOLDIER; 
   } 

   if( ent->client->sess.latchPlayerType < PC_SOLDIER || ent->client->sess.latchPlayerType > PC_COVERTOPS ) { 
      ent->client->sess.latchPlayerType = PC_SOLDIER; 
   } 

   if( !SetTeam( ent, s, qfalse, w, w2, qtrue ) ) { 
      G_SetClientWeapons( ent, w, w2, qtrue ); 
   } 
}

(Demolama) #2

problem with that though… is although you do have a class limit… it isnt based off of anything but the max amount of players the server allows… so lets say you wanted to allow 8 medics per team during a full server but only 4 when the server is less than half full… this current code does not allow that

and it also doesnt limit per team… while having 4 coverts on defense would seem a bit much… on offense however it could be just enough

adding a percentage option is a better way to handle this problem along with a per team per class max cvar

an indication of what classes are still available for new clients to choose from would also be a nice feature


if you look at the picture above the numbers at the bottom of the screen represent the number classes available and the number of classes in use… this indicator lets clients know what classes they can choose from and what ones they cant

The code above also makes it so that if the class cant be used it makes you a soldier with an smg :banghead:

just some things to think about if you want to step this idea up to the next level


(Azyu) #3

Thanks for your advice, Demoman.
Your idea is really good. I’ll try it. :smiley:


(Demolama) #4

np… its just some things I thought about and got feedback from to get all the ideas Ive used in lamapro’s class limitation