PlanetQuake | Code3Arena | Tutorials | << Prev | Tutorial 20 | Next >>


  • Home/News
  • ModSource
  • Compiling
  • Help!!!
  • Submission
  • Contributors
  • Staff
  • Downloads

    < Index >
    1. Mod making 101
    2. Up 'n running
    3. Hello, QWorld!
    4. Infinite Haste
    5. Armor Piercing Rails
    6. Bouncing Rockets
    7. Cloaking
    8. Ladders
    9. Favourite Server
    10. Flame Thrower
    11. Vortex Grenades
    12. Grapple
    13. Lightning Discharge
    14. Locational Damage
    15. Leg Shots
    16. Weapon Switching
    17. Scoreboard frag-rate
    18. Vortex Grenades II
    19. Vulnerable Missiles
    20. Creating Classes
    21. Scrolling Credits
    22. Weapon Dropping
    23. Anti-Gravity Boots
    24. HUD scoreboard
    25. Flashlight and laser
    26. Weapon Positioning
    27. Weapon Reloading
    28. Progressive Zooming
    29. Rotating Doors
    30. Beheading (headshot!)
    31. Alt Weapon Fire
    32. Popup Menus I
    33. Popup Menus II
    34. Cluster Grenades
    35. Homing Rockets
    36. Spreadfire Powerup
    37. Instagib gameplay
    38. Accelerating rockets
    39. Server only Instagib
    40. Advanced Grapple Hook
    41. Unlagging your mod

    < Index >
    1. Entities
    2. Vectors
    3. Good Coding
    4. Compilers I
    5. Compilers II
    6. UI Menu Primer I
    7. UI Menu Primer II
    8. UI Menu Primer III
    9. QVM Communication, Cvars, commands
    10. Metrowerks CodeWarrior
    11. 1.27g code, bugs, batch


  • Quake3 Files
  • Quake3 Forums
  • Q3A Editing Message Board
  • Quake3 Editing


  • SumFuka
  • Calrathan
  • HypoThermia
  • WarZone

    Site Design by:
    ICEmosis Design

    TUTORIAL 20 - Creating Classes
    by Fritz

    This tutorial is intended to help you create a class based mod in which players can choose from a variety of classes, each with its own unique abilities/attributes. When this tutorial is completed you should be able to choose your class (by selecting a model) and recieve different weapons and attributes based on the class you chose.

    There are only 4 simple steps to this tutorial, so let's get started.

    Files you will need to modify:

    1. Defining (bg_public.h g_local.h)

    First we have to define a type to keep track of the different classes. Lets start out with 3 simple classes.

    Open the file bg_public.h and Go to about line 428

    typedef enum {
    } team_t;
    typedef enum {
    } pclass_t;

    Next we will need a playerclass variable to keep track of what class we are, and a newplayerclass variable to store the new class we will become when we respawn.

    Open the file g_local.h and about line 213 you will find the clientPersistent structure.

    typedef struct {
       clientConnected_t	connected;
       usercmd_t	cmd;		   // we would lose angles if not persistant
       qboolean	localClient;	   // true if "ip" info key is "localhost"
       qboolean	initialSpawn;	   // the first spawn should be at a cool location
       qboolean	predictItemPickup; // based on cg_predictItems userinfo
       char		netname[36];
       int		maxHealth; // for handicapping
       int		enterTime; // level.time the client entered the game
       playerTeamState_t teamState;	   // status in teamplay games
       int		voteCount; // to prevent people from constantly calling votes
       qboolean	teamInfo;	   // send team overlay updates?
       pclass_t	playerclass;	   // The players current class
       pclass_t	newplayerclass;	   // The class the player will become when it respawns
    } clientPersistant_t;

    This data structure is part of the gclient_t structure, and can be accessed through a gclient_t or gentity_t pointer (see below).

    2. Choosing Classes (g_client.c)

    Ok, now we have to assign values to our newplayerclass variable when the player selects a model. The function we are about to edit is called when a client first connects to the server and whenever the player changes his user info.

    Go to about line 621 and you will find the ClientUserInfoChanged() function. Notice how the gclient_t structure is accessed from the gentity_t pointer.

    // set model
    Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) );
    if (!Q_stricmp (model, "biker/red"))
       client->pers.newplayerclass = PCLASS_BFG;
    else if (!Q_stricmp (model, "anarki/blue"))
       client->pers.newplayerclass = PCLASS_LIGHTNING;
    else if (!Q_stricmp (model, "grunt/red"))
       client->pers.newplayerclass = PCLASS_RAILGUN;
    else {
       client->pers.newplayerclass = PCLASS_BFG;
       Q_strncpyz( model, "biker/red", sizeof( model ) );
    client->pers.playerclass = client->pers.newplayerclass;
    So far there are only class values for a couple of models, but you could easily assign values to the rest of the models. You could also assign the same number to multiple models, which would be useful if you wanted to make all the biker models, or all the larger models, etc. the same class.

    If the player chooses a model that has not been assigned a class variable then they will be set to the first class by default and be given the "biker/red" model.

    3.Updating The Class(g_client.c)

    Once a player has died we want to put the newplayerclass into playerclass when they respawn.
    Go down to about line 935 in the ClientSpawn() function.
    ent->flags = 0;
    client->pers.playerclass = client->pers.newplayerclass;
    You are finished creating your class system! You should see if your code compiles correctly at this point, but there will be absolutely no noticable changes if you run it.

    2. Assigning stuff to the classes (g_client.c)

    The final thing you have to do is give the players different stuff depending on what class they are.

    Go to about line 945 in the ClientSpawn() function.

    if ( g_gametype.integer == GT_TEAM ) {
       client->ps.ammo[WP_MACHINEGUN] = 50;
    } else {
       client->ps.ammo[WP_MACHINEGUN] = 100;
    //assign weapons according to class
    switch (client->pers.playerclass){
       case PCLASS_BFG:
          client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BFG );
          client->ps.ammo[WP_BFG] = 20;
          client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_LIGHTNING );
          client->ps.ammo[WP_LIGHTNING] = 60;
       case PCLASS_RAILGUN:
          client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_RAILGUN );
          client->ps.ammo[WP_RAILGUN] = 20;
    You now have working classes! Right now the only thing that distinguishes the classes are the weapons they begin with but you could easily give them different speeds, health, armour, special abilities, etc. So now its your job to flesh out your classes and make your mod interesting.

    If you have any questions you'd like to ask me please e-mail me Fritz

    PlanetQuake | Code3Arena | Tutorials | << Prev | Tutorial 20 | Next >>