Timed Clan Match Mode!

    This little modification lets the server run timed matches!  Upon entering the server, players will be able to pick up weapons and shoot, but no damage will be delt.  Once the pre-match timer expires, everyone will respawn and the match will begin!

For this tutorial you need to have added .ini file support to your mod.

  It must be working!   You may find the .ini file tutorial at Inside 3d:

.ini file tutorial

 

Now if you have completed the .ini file tutorial and it WORKS, we'll get started.

Add in the blue code and take out any pink code.


P_CLIENT.C modifications:

Inside ClientBeginDeathmatch after:

    ClientEndServerFrame (ent);

put this:



    if (ent == &g_edicts[1] && clanmatch->value)// first player to connect, set prematch timers if in clanmatch
    {
        char *p;
        int t;

        // first we make sure that the .ini file is open
        if (ini_file.ini_file_read)
        {
            p = Ini_GetValue(&ini_file, "Clanmatch", "PreDMTime");
        // check that what was returned wasn't NULL
        if (p != NULL)
            {
                t = atoi(p);
            }
            else
                gi.dprintf("Value of PreDMTime in MYMOD.INI = NULL\n"); // change this
        }
        else
            gi.error("Ini file not loaded, in Pre DM Time Setup");

        if (t < 30) // you have to have at LEAST a 30 second timer
            predmtime = level.time + 65; // set dm timer
        else
            predmtime = level.time + t; // add it

        timer = true;
    }

 

This sets up the Pre DM Timer if you are the first player to connect. Now in ClientThink after:

    client = ent->client;

put this:



    if (timer && clanmatch->value && ent == &g_edicts[1]) // dm timer is on and we're the first client
    {
        int time_left = (predmtime - level.time);
        static int last_time_left;

        if (time_left > 0) // timer is clicking
        {
            if (time_left == 300 && last_time_left != 300)
            {
                last_time_left = 300;
                gi.bprintf(PRINT_HIGH, "Five Minutes until match.\n");
            }
            else if (time_left == 120 && last_time_left != 120)
            {
                last_time_left = 120;
                gi.bprintf(PRINT_HIGH, "Two Minutes until match.\n");
            }
            else if (time_left == 60 && last_time_left != 60)
            {
                last_time_left = 60;
                gi.bprintf(PRINT_HIGH, "One Minute until match.\n");
            }
            else if (time_left == 30 && last_time_left != 30)
            {
                last_time_left = 30;
                gi.bprintf(PRINT_HIGH, "Thirty seconds until match.\n");
            }
            else if (time_left == 15 && last_time_left != 15)
            {
                last_time_left = 15;
                gi.bprintf(PRINT_HIGH, "Fifteen seconds until match.\n");
            }
            else if (time_left == 10 && last_time_left != 10)
            {
                last_time_left = 10;
                gi.bprintf(PRINT_HIGH, "Ten seconds until match.\n");
            }
            else if (time_left == 9 && last_time_left != 9)
            {
                last_time_left = 9;
                gi.bprintf(PRINT_HIGH, "Nine seconds until match.\n");
            }
            else if (time_left == 8 && last_time_left != 8)
            {
                last_time_left = 8;
                gi.bprintf(PRINT_HIGH, "Eight seconds until match.\n");
            }
            else if (time_left == 7 && last_time_left != 7)
            {
                last_time_left = 7;
                gi.bprintf(PRINT_HIGH, "Seven seconds until match.\n");
            }
            else if (time_left == 6 && last_time_left != 6)
            {
                last_time_left = 6;
                gi.bprintf(PRINT_HIGH, "Six seconds until match.\n");
            }
            else if (time_left == 5 && last_time_left != 5)
            {
                last_time_left = 5;
                gi.bprintf(PRINT_HIGH, "Five seconds until match.\n");
            }
            else if (time_left == 4 && last_time_left != 4)
            {
                last_time_left = 4;
                gi.bprintf(PRINT_HIGH, "Four seconds until match.\n");
            }
            else if (time_left == 3 && last_time_left != 3)
            {
                last_time_left = 3;
                gi.bprintf(PRINT_HIGH, "Three seconds until match.\n");
            }
            else if (time_left == 2 && last_time_left != 2 && last_time_left != 5)
            {                                                                    
                last_time_left = 2;
                gi.bprintf(PRINT_HIGH, "Two seconds until match.\n");
            }
            else if (time_left == 1 && last_time_left != 1)
            {
                last_time_left = 1;
                gi.bprintf(PRINT_HIGH, "One second until match.\n");
            }
        }
        else // timer done
        {
            edict_t *tokill;
            int i;
            level.framenum = 0;
            centerprint_all("<<< LOCK AND LOAD!!! >>>\n");
            for_each_player(tokill, i)
            {
                PutClientInServer (tokill);
                // send effect
                gi.WriteByte (svc_muzzleflash);
                gi.WriteShort (tokill-g_edicts);
                gi.WriteByte (MZ_LOGIN);
                gi.multicast (tokill->s.origin, MULTICAST_PVS);   
                tokill->svflags &= ~SVF_NOCLIENT;
            }

            timer = false;
        }
    }

 

Notice that level.framenum is set to 0, thereby making the round last as long as the timelimit.  Before, it would be counting the time while waiting for the match to start.  Now it will be timed accordingly.

G_SAVE.C modifications:

Inside InitGame after it initializes the deathmatch cvar:



    clanmatch = gi.cvar ("clanmatch", "0", CVAR_LATCH);

 

G_MAIN.C modifications:

At the top after it does the cvar_t for deathmatch:



cvar_t    *clanmatch;

 

And now inside CheckDMRules after if says:

    if (timelimit->value)
    {

and INSIDE this if brace, put this:



        if (clanmatch->value)
        {
            if ((level.time == ((timelimit->value - 2) * 60)) && last_time != 200)
            {
                last_time = 200;
                gi.bprintf(PRINT_HIGH, "Two minutes left in match.\n");
            }
            else if ((level.time == ((timelimit->value - 1) * 60)) && last_time != 100)
            {
                last_time = 100;
                gi.bprintf(PRINT_HIGH, "One minute left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 30)) && last_time != 30)
            {
                last_time = 30;
                gi.bprintf(PRINT_HIGH, "30 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 10)) && last_time != 10)
            {
                last_time = 10;
                gi.bprintf(PRINT_HIGH, "10 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 9)) && last_time != 9)
            {
                last_time = 9;
                gi.bprintf(PRINT_HIGH, "9 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 8)) && last_time != 8)
            {
                last_time = 8;
                gi.bprintf(PRINT_HIGH, "8 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 7)) && last_time != 7)
            {
                last_time = 7;
                gi.bprintf(PRINT_HIGH, "7 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 6)) && last_time != 6)
            {
                last_time = 6;
                gi.bprintf(PRINT_HIGH, "6 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 5)) && last_time != 5)
            {
                last_time = 5;
                gi.bprintf(PRINT_HIGH, "5 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 4)) && last_time != 4)
            {
                last_time = 4;
                gi.bprintf(PRINT_HIGH, "4 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 3)) && last_time != 3)
            {
                last_time = 3;
                gi.bprintf(PRINT_HIGH, "3 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 2)) && last_time != 2)
            {
                last_time = 2;
                gi.bprintf(PRINT_HIGH, "2 seconds left in match.\n");
            }
            else if ((level.time == ((timelimit->value * 60) - 1)) && last_time != 1)
            {
                last_time = 1;
                gi.bprintf(PRINT_HIGH, "1 second left in match.\n");
            }
        }
        if (level.time >= timelimit->value*60)
        {
            if (clanmatch->value)
                gi.bprintf (PRINT_HIGH, "The match is over.\n");
            else
                gi.bprintf (PRINT_HIGH, "Timelimit hit.\n");
            EndDMLevel ();
            return;
        }

        if (level.time >= timelimit->value*60)
        {
            gi.bprintf (PRINT_HIGH, "Timelimit hit.\n");
            EndDMLevel ();
            return;
        }

 

G_COMBAT.C modifications:

Now at the top of T_Damage put this:



    if (clanmatch->value && timer)
        return;

This provides you can't be damaged in the pre-dm mode.

P_HUD.C modifications:

Inside G_SetStats after:

    ent->client->ps.stats[STAT_HEALTH] = ent->health;

put:



    if (timer)
        ent->client->ps.stats[STAT_PREDM] = 1;
    else
        ent->client->ps.stats[STAT_PREDM] = 0;

 

 

This sets up the PRE-DEATHMATCH MODE display.

G_LOCAL.H modifications:

Inside the extern cvar_t definitions after the one for deathmatch put:



extern    cvar_t    *clanmatch;

 

And at the bottom of the file put this:



qboolean timer;
int predmtime;
int last_time;

void centerprint_all (char *msg);
#define for_each_player(TOKILL,INDEX)\
for(INDEX=1;INDEX<=maxclients->value;INDEX++)\
    if ((TOKILL=&g_edicts[i]) && TOKILL->inuse)

That sets up the variables.

Q_SHARED.H modifications:

Inside the STAT_x declarations put this (if 31 is not used, else make those substitutions below):



#define STAT_PREDM                 31

G_SPAWN.C modifications:

Iniside the dm_statusbar macro, find this section of code:

// chase camera
"if 16 "
"xv 0 "
"yb -68 "
"string \"Chasing\" "
"xv 64 "
"stat_string 16 "
"endif "
;

and change it to this:



// chase camera
"if 16 "
"xv 0 "
"yb -68 "
"string \"Chasing\" "
"xv 64 "
"stat_string 16 "
"endif "

"if 31 " // if in predm timer
"xv 0 " // set the x
"yb -58 " // and y positions
"string2 \"PREDM COUNTDOWN MODE\" " // and print this in green
"endif "
;

G_UTILS.C modifications:

Add this function to the bottom of g_utils.c:

/*
===================
Centerprint_All
===================
*/

void centerprint_all (char *msg)
{
    int i;
    edict_t *tokill;

    for_each_player(tokill,i)
    {
        gi.centerprintf (tokill, msg);
    }
}

 

That's it! MAKE SURE YOU HAVE FOLLOWED THE INI FILE TUTORIAL ON INSIDE3D.COM AND HAVE YOUR INI FILE
SET UP, INITIALIZED, AND IN THE VARIABLE ini_file. IT __WILL NOT WORK__ IF YOU HAVE NOT DONE THIS!

Aside from that, you have clanmatch mode now.

This mode is fully transparent, meaning let's say you have DM, Team DM, and CTF (using my mod FireTeam
as an example). With the addition of clanmatch, with no extra coding, you can have Clan DM, Clan Team DM,
and Clan CTF, just by adding +set clanmatch 1.

Hope you guys use this!

Tutorial by Psykotik