QuakeZone
MOD Coding Tutorials
Quake II Coding Tutorials!

Introduction
Code
Notes
Exercises
Quake II Coding Tutorials

12 Anti-Camping Mod

Introduction Introduction

This little tutorial shows you how to put paid to those annoying little campers once and for all.

Code Code


g_local.h

Add the following lines as indicated:

#define MOD_ANTI_CAMPING	43 		// PJT - anti-camping
#define MOD_FRIENDLY_FIRE	0x8000000	// PJT <-- insert before this line
		
At the end of the cvar list, add the following cvars:
// PJT - anti-camping
extern cvar_t *sv_campdelay;			// delay before countdown
extern cvar_t *sv_campcount;			// duration of countdown
extern cvar_t *sv_camprange;			// anti-camping radius
// PJT
		
Add the folloiwng lines to the end of the gclient_s sctructure:
	float		camp_timer1;		// PJT - anti-camping timer
	float		camp_timer2;		// PJT - anti-camping timer
	vec3_t		camp_origin;		// PJT - anti-camping, last position
		

p_client.c

Add the following cvar variables immediately after the include statemenst at the top of the file:

cvar_t *sv_campdelay;	// PJT - anti-camping..
cvar_t *sv_campcount;	// PJT - ..see g_local.h..
cvar_t *sv_camprange;	// PJT - ..for description	
		
In procedure ClientObituary add the following lines as indicated:
		// PJT - anti camping
      	case MOD_ANTI_CAMPING:
          	message="was a camping whore...now he/she isn't any more...(all sing)";
          	break;
		// PJT
	case MOD_BOMB:
	case MOD_SPLASH:
	case MOD_TRIGGER_HURT:
		message = "was in the wrong place";
		break;

		....

		// PJT - anti camping
      		case MOD_ANTI_CAMPING:
        	  	message="was a camping whore...now he/she isn't any more...(all sing)";
        	  	break;
			// PJT

			default:
				if (IsNeutral(self))
					message = "killed itself";

		....
		
At the end of procedure PutClientInserver add the following lines:
	// PJT - initialise anti-camping timers
	client->camp_timer1		= level.time;
	client->camp_timer2 		= sv_campdelay->value + sv_campcount->value;
	VectorCopy(ent->s.origin, ent->client->camp_origin);
	// PJT
		
At the start of procedure ClientThink add the folloiwng lines:
	// PJT - anti camping
	// call camping detector every 1 second
	if ((!ent->deadflag) && !(ent->client->camp_timer1 > level.time))
	{
		camping_think(ent);
		ent->client->camp_timer1 = level.time + 1.0;
		if (ent->health < 1) return;
	}
	// PJT
		
Immediately after procedure ClientThink, insert the following new procedure:
// PJT - anti-camping
void camping_think(edict_t *ent)
{
	int 		distance;	// PJT - anti-camping
	vec3_t 		forward;	// PJT - anti-camping

	// check for not re-spawning
	if((level.time - ent->client->respawn_time) < 5)
		return;

	// 1. check for new distance from previous camping origin
    VectorSubtract(ent->s.origin, ent->client->camp_origin, forward);
    distance=(int)VectorLength(forward);

	// 2. if within radius, check timer
	if (distance < sv_camprange->value)
	{
		ent->client->camp_timer2--;
		if (ent->client->camp_timer2 < 1)								// countdown expired - kill player
		{
			ent->health = 0;
			meansOfDeath = MOD_ANTI_CAMPING;
			player_die (ent, ent, ent, 100000, vec3_origin);
			ent->client->camp_timer2 = sv_campdelay->value + sv_campcount->value;
		}
		else if (ent->client->camp_timer2 < sv_campcount->value +1)		// start countdown
		{
			gi.sound(ent, CHAN_VOICE, gi.soundindex("world/x_alarm.wav"), 1, ATTN_NORM, 0);
			gi.centerprintf (ent, "Camping alert: %i seconds to destruction.\n", (int)(ent->client->camp_timer2));
		}
		// else let delay run down before starting countdown
	}

	// 3. outside radius, reset timer and orgin
	else
	{
		ent->client->camp_timer2 = sv_campdelay->value + sv_campcount->value;
		VectorCopy(ent->s.origin, ent->client->camp_origin);
	}
}
		

g_save.c

At the end of procedure InitGame add the following lines:
	// PJT - anti-camping
	sv_campdelay = gi.cvar("sv_campdelay","5", CVAR_SERVERINFO);	// delay before countdown starts
	sv_campcount = gi.cvar("sv_campcount","5", CVAR_SERVERINFO);	// length of countdown
	sv_camprange = gi.cvar("sv_camprange","10", CVAR_SERVERINFO);	// range for anti-camping detection
	// PJT
		

cmds.cfg

Add the following lines to your config file:
set sv_campdelay    5.0
set sv_campcount    5.0
set sv_camprange    10
		
Notes Notes to code


g_local.h
  • MOD_ANTI_CAMPING is a flag to indicate death messages
  • the 3 server (cvar) variables are added here as externs so that they can be referenced by any piece of code
  • there are 2 timers and a copy of the player's last position stored in the client structure

p_client.c
  • the 3 cvars are first defined in this piece of code
  • ClientObituary works out the correct death message, and is modified for an anti-camping death
  • the new client fields are intiialised in PutClientInServer
  • ClientThink is amended to decrement the camping check timer (timer1) every second - when it expired camping_think is called, timer1 is reset and if the player has been killed (health = 0) the procedure is exited
  • camping_think does what it says on the label:
    • returns if player has just spawned
    • calculates distance from previous position 1 second ago
    • if player is within camping radius, checks timer 2 - if greater than countdown cvar value, does nothing
    • if less than countdown cvar value, sends message to player
    • if timer 2 goes to zero, player is killer with appropriate message
    • if player is outside radius, timer2 is reset and new position is stored

g_save.c
  • cvar variables are read in InitGame

cmds.cfg
  • cvar variables are set in your config file:
    • sv_campdelay sets delay before countdown
    • sv_campcount sets length of countdown
    • sv_campradius sets radius of anti-camping detection
Exercises Exercises

  • set sv_campdelay to a high value (9999) to disable anti-camping
  • set sv_campdelay to a low value and the other 2 cvars to larger values to keep the players running around


Page last updated 26th September 2000