#include "defs.qh"
#include "menu.qh"
#include "skins.qh"
/*======================================================
	TFORT.QC			Custom TeamFortress v3.2	

	(c) TeamFortress Software Pty Ltd 	29/2/97
	(c) William Kerney			9/16/00
	(c) Craig Hauser				19/3/00
========================================================
Class handling and other utility functions
======================================================*/
// Function Prototypes
//void() RemoveFlare;
void() GrenadeExplode;
void() spike_touch;
void(entity p) bound_other_ammo;
void(entity Goal, entity Player, entity Item) DisplayItemStatus;
void (entity targ, entity inflictor, entity attacker, float damage, float T_flags, float T_AttackType) TF_T_Damage;

// Map Function Prototypes
void(entity Item, entity AP, float method) tfgoalitem_RemoveFromPlayer;

// Help Functions
void() TeamFortress_MOTD;

// Team Functions
float(float tno) TeamGetColor;
void(float tno) TeamFortress_TeamSetColor;
float() TeamFortress_TeamPutPlayerInTeam;
float(float tno) TeamFortress_TeamGetScore;
float(float tno) TeamFortress_TeamGetIllegalClasses;

//WK
void() DropToCustomClassGen; //In custom.qc
float() W_BestWeapon; //In weapons.qc
void() FragGrenadeTouch; //In custom.qc
void() FragGrenadeExplode;
void() KracGrenadeTouch;
void() KracGrenadeExplode;
void() AntiGravGrenadeExplode;
void() Autoitem_think;
void() DetonateAllGuns;

// Impulse Functions
void() TeamFortress_ChangeClass;
void() TeamFortress_DisplayLegalClasses;
void() TeamFortress_Inventory;
void() Grunty_StateInv;
void() TeamFortress_ShowTF;
void() TeamFortress_PrimeGrenade;
void() TeamFortress_ThrowGrenade;
void() TeamFortress_DisplayDetectionItems;

// Player Class Handling Functions
float(float pc) IsLegalClass;
//void() TeamFortress_SetAlias; //WK
void() TeamFortress_SetHealth;
void() TeamFortress_SetEquipment;
void(entity p) TeamFortress_SetSpeed;
void(entity p) TeamFortress_SetSkin;
void(entity Viewer, float pc, float rpc) TeamFortress_PrintClassName;
void() TeamFortress_RemoveTimers;
void(float Suicided) TeamFortress_SetupRespawn;
void() TeamFortress_CheckClassStats;
float(entity Retriever, float AmmoType) TeamFortress_GetMaxAmmo;
float(entity Retriever, float WeaponType) TeamFortress_CanGetWeapon;
float(entity Retriever, entity Items) TeamFortress_AddBackpackItems;
float(entity Player, float Armorclass) TeamFortress_DescribeArmor;
#ifdef SPEECH
void(entity player) TeamFortress_SayClassName;
#endif

// AmmoBox Handling Functions
void () TeamFortress_AmmoboxTouch;
float (float tno) num_team_ammoboxes;
void(float tno) RemoveOldAmmobox;
void(float tno) increment_team_ammoboxes;
void(float tno) decrement_team_ammoboxes;

// Weapon Handling Functions
void() TeamFortress_ExplodePerson;
void() NormalGrenadeTouch;
void() NormalGrenadeExplode;
void() PlayerObserverMode;

// Utility Functions
void(string halias, float himpulse1, float himpulse2) TeamFortress_Alias;

// Cyclic Event Functions
void() TeamFortress_Regenerate;
void() TeamFortress_RegenerateCyber;
void() TeamFortress_RegenerateCells;

//CH
float(entity p) Return_Custom_Skins;

//- OfN
void() FlareGrenadeTouch;
void() FlareGrenadeExplode;
void() FlareBounce;
void(entity sld) grunty_boundammo;
void(entity player) UpdateCells;
void () BioGrenadeTouch;
void () BioGrenadeExplode;
float(entity theplayer, float grenslot) GetMaxGrens;

//=========================================================================
// IMPULSE FUNCTIONS
//=========================================================================
// Uses a class dependant special skill
void() UseSpecialSkill =
{
	self.impulse = 0;

	if (self.cutf_items & CUTF_SENTRYGUN || self.tf_items & NIT_TESLA || self.tf_items & NIT_SECURITY_CAMERA || self.tf_items & NIT_TELEPORTER || self.cutf_items & CUTF_DISPENSER || self.cutf_items & CUTF_FIELDGEN)
		self.impulse = TF_ENGINEER_BUILD;
	else if (self.cutf_items & CUTF_SPY_KIT)
		self.impulse = TF_SPY_SPY;
	else if (self.weapons_carried & WEAP_GRENADE_LAUNCHER)
		self.impulse = TF_PB_DETONATE;
	else if (self.tf_items & NIT_SCANNER)
		self.impulse = TF_SCAN_30;
	else if (self.weapons_carried & WEAP_SNIPER_RIFLE)
		self.impulse = TF_AUTOZOOM;
	else
		self.impulse = TF_RELOAD;

	//WK Since most people don't know "disguise" or "build"
	// we'll allow them to toggle between the two with special.
	// This wipes out .money, so watch out for side effects.
	if (!(self.done_custom & CUSTOM_BUILDING) && (self.impulse == TF_ENGINEER_BUILD) && (self.cutf_items & CUTF_SPY_KIT))
	{
		if (self.money) self.money = 0;
		else self.money = 1;

		if (self.money)
			self.impulse = TF_ENGINEER_BUILD;
		else 
		{
			if (self.effects & (EF_DIMLIGHT | EF_BRIGHTLIGHT)) //CH why not have the check here too, saves a keypress
				self.impulse = TF_ENGINEER_BUILD;
			else
				self.impulse = TF_SPY_SPY;
		}
	}
};


//=========================================================================
// Player change class function
// If self.impulse == 1, change to Civilian class
void() TeamFortress_ChangeClass =
{
	local entity spot, te;

	//WK - Handle Custom Class Restarting
	if (self.playerclass == PC_CUSTOM && (self.done_custom & CUSTOM_BUILDING)) {
		DropToCustomClassGen();	//Comatose state
		return;
	}

	if (self.playerclass != PC_UNDEFINED)
	{
		// In Deathmatch 3, you can change class after you die
		if (deathmatch != 3)
			return;

		// Civilian Teams can never change class
		if (TeamFortress_TeamIsCivilian(self.team_no))
		{
			sprint(self, PRINT_HIGH, "You're a civilian. Learn to live with it.\n");

			return;			
		}

		if (!IsLegalClass(self.impulse - TF_CHANGEPC))
		{
			sprint(self, PRINT_HIGH, "Your team cannot play that class.\n");

			TeamFortress_DisplayLegalClasses();
			return;
		}

		self.nextpc = self.impulse - TF_CHANGEPC;
		//WK - Handle Custom Class
		if (self.nextpc == PC_CUSTOM)
		{
			self.done_custom = self.done_custom | CUSTOM_ON_SPAWN; //Generate a new custom class when we respawn
		}
		sprint(self, PRINT_HIGH, "After dying, you will return as a new class\n");
		return;
	}

	// players must join a team, if teamplay is on
	if (teamplay && self.team_no == 0) 
	{
		sprint(self, PRINT_HIGH, "You must join a team first. \n");
		return;
	}

	// Only change if you've got any lives left
	if ( self.lives == 0 )
	{
		sprint(self, PRINT_HIGH, "You have no lives left.\n");

		return;
	}

	if (!IsLegalClass(self.impulse - TF_CHANGEPC) && (self.impulse != 1))
	{
		sprint(self, PRINT_HIGH, "You cannot play that playerclass on this map. \n");

		TeamFortress_DisplayLegalClasses();
		return;
	}

	// Spy may be disabled
	if ((spy_off == TRUE) && ((self.impulse - TF_CHANGEPC) == PC_SPY))
	{
		sprint(self, PRINT_HIGH, "The spy class has been disabled on the server by the administrator.\n");
		return;
	}

	if (self.impulse != 1)
		self.playerclass = self.impulse - TF_CHANGEPC;
	else
		self.playerclass = PC_CIVILIAN;

	self.nextpc = 0;

	// Turn off PC_UNDEFINED's nomove and invincibility
	self.takedamage = DAMAGE_AIM;
	//WK Prevent bad movetype errors, or something
	if (self.classname != "player") {
		RPrint("BUG BUG BUG BUG BUG BUG BUG BUG BUG\n");
		RPrint("Non-player was in tfort.qc::changeclass()!\n");
		return;
	}
	self.movetype = MOVETYPE_WALK;
	self.flags = FL_CLIENT | FL_ONGROUND;
	self.waterlevel = 0;
	self.air_finished = time + 12;

	// give them a model, and a new spawn point
	self.solid = SOLID_SLIDEBOX;
	// pausetime is set by teleporters to keep the player from moving a while
	self.pausetime = 0;
	
	spot = SelectSpawnPoint ();

#ifdef MAP_DEBUG
	RPrint(self.netname);
	RPrint(" spawned at a ");
	RPrint(spot.netname);
	if (spot.team_no != 0)
	{
		RPrint(", team_no of ");
		st = ftos(spot.team_no);
		RPrint(st);
	}
	RPrint("\n");
#endif

	self.origin = spot.origin + '0 0 1';
	self.angles = spot.angles;
	self.fixangle = TRUE;		// turn this way immediately

	setmodel (self, "");
	modelindex_null = self.modelindex;

	setmodel (self, "progs/eyes.mdl");
	modelindex_eyes = self.modelindex;

	setmodel (self, "progs/player.mdl");
	modelindex_player = self.modelindex;

	setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);	

	self.view_ofs = '0 0 22';
	player_stand1 ();
/*	if (deathmatch || coop)
	{
		makevectors(self.angles);
		spawn_tfog (self.origin + v_forward*20);
	}*/
	makevectors (self.angles);
	spawn_tfog (self.origin + v_forward * 20);
	spawn_tdeath (self.origin, self);

	// Display chosen class
	if ( self.playerclass == PC_RANDOM )
	{
		sprint(self, PRINT_HIGH, "Random Playerclass.\n");

		self.tfstate = (self.tfstate | TFSTATE_RANDOMPC);
		self.playerclass = 1 + floor(random() * (PC_RANDOM - 1));
	}

	// If this is a TeamSpawnpoint, check to see if it
	// gives out a GoalItem, or displays a message
	if (spot.classname == "info_player_teamspawn")
	{
		if (spot.items != 0)
		{
			te = Finditem(spot.items);
			if (te)
				tfgoalitem_GiveToPlayer(te, self, self);

			if (!(spot.goal_activation & TFSP_MULTIPLEITEMS))
				spot.items = 0;
		}

		if (spot.message)
		{
			CenterPrint(self, spot.message);

			if (!(spot.goal_activation & TFSP_MULTIPLEMSGS))
				spot.message = "";
		}

		// TeamSpawn points can remove themselves after being spawned on
		if (spot.goal_effects == TFSP_REMOVESELF)
		{
			spot.classname = "deadpoint";
			spot.team_str_home = "";
			spot.nextthink = time + 1;
			spot.think = SUB_Remove;
		}
	}

	//WK - Handle Custom Class
	if (self.playerclass == PC_CUSTOM) {
		DropToCustomClassGen();	//Comatose state 
	}

	ResetMenu();
	TeamFortress_PrintClassName(self,self.playerclass, (self.tfstate & TFSTATE_RANDOMPC));
#ifdef SPEECH
	TeamFortress_SayClassName(self);
#endif
	TeamFortress_SetEquipment();
	TeamFortress_SetHealth();
	TeamFortress_SetSpeed(self);
	TeamFortress_SetSkin(self);
	//WK Give them invincibility if they are a normal class or bought it
	if (self.playerclass >= PC_SCOUT && self.playerclass <= PC_RANDOM) {
		self.items = self.items & IT_INVULNERABILITY;
		self.invincible_time = 1;
		self.invincible_finished = time + RESPAWN_GUARD_TIME;
	}
};

//=========================================================================
// Display a list of all the legal classes for this map
void() TeamFortress_DisplayLegalClasses =
{
	local float gotone, ill;

	sprint(self, PRINT_HIGH, "Legal Classes for your team are:\n");
	gotone = FALSE;

	ill = TeamFortress_TeamGetIllegalClasses(self.team_no);

	if (!(illegalclasses & TF_ILL_SCOUT) && !(ill & TF_ILL_SCOUT))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Scout");
	}
	if (!(illegalclasses & TF_ILL_SNIPER) && !(ill & TF_ILL_SNIPER))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Sniper");
	}
	if (!(illegalclasses & TF_ILL_SOLDIER) && !(ill & TF_ILL_SOLDIER))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Soldier");
	}
	if (!(illegalclasses & TF_ILL_DEMOMAN) && !(ill & TF_ILL_DEMOMAN))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Demolitions Man");
	}
	if (!(illegalclasses & TF_ILL_MEDIC) && !(ill & TF_ILL_MEDIC))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Combat Medic");
	}
	if (!(illegalclasses & TF_ILL_HVYWEP) && !(ill & TF_ILL_HVYWEP))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Heavy Weapons Guy");
	}
	if (!(illegalclasses & TF_ILL_PYRO) && !(ill & TF_ILL_PYRO))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Pyro");
	}
	if (!(illegalclasses & TF_ILL_SPY) && !(ill & TF_ILL_SPY))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Spy");
	}
	if (!(illegalclasses & TF_ILL_ENGINEER) && !(ill & TF_ILL_ENGINEER))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "Engineer");
	}
	if (!(illegalclasses & TF_ILL_RANDOMPC) && !(ill & TF_ILL_RANDOMPC))
	{
		if (gotone)
			sprint(self, PRINT_HIGH, ", ");
		gotone = TRUE;
		sprint(self, PRINT_HIGH, "RandomPC");
	}

	sprint(self, PRINT_HIGH, "\n");
};

//=========================================================================
// Displays the player's inventory
void() TeamFortress_Inventory =
{
	local entity tg;
	local string ac;
	local float col;
	local float special; //CH used to determine if a \n is needed for a line
	special = 0;

	if (self.demon_one.classname == "monster_army")
	{
		local entity oself;
		
		oself = self;
		self = self.demon_one;
		Grunty_StateInv();
		self = oself;
	}

	// Display Team
	col = TeamGetColor(self.team_no);

	sprint(self, PRINT_HIGH, "You're in team ");
	ac = ftos(self.team_no);
	sprint(self, PRINT_HIGH, ac);
	sprint(self, PRINT_HIGH, ", color ");
	ac = ftos(col);
	sprint(self, PRINT_HIGH, ac);
	sprint(self, PRINT_HIGH, ".\n");

	// Display Lives, if applicable
	if (self.lives != -1)
	{
		ac = ftos(self.lives);

		sprint(self, PRINT_HIGH, "You've got ");
		sprint(self, PRINT_HIGH, ac);
		if (self.lives == 1)
			sprint(self, PRINT_HIGH, " life.\n");
		else 
			sprint(self, PRINT_HIGH, " lives.\n");

	}

	// Display Number of Grenades of each type
	//WK Fix BUG grenades
	if (self.tp_grenades_1 == 0)
		self.no_grenades_1 = 0;
	if (self.tp_grenades_2 == 0)
		self.no_grenades_2 = 0;

	if (self.no_grenades_1 > 0)
	{
		sprint(self, PRINT_HIGH, "Gren.Type 1: ");
		if (self.tp_grenades_1 == GR_TYPE_NORMAL)
			sprint(self, PRINT_HIGH, "Normal(");
		else if (self.tp_grenades_1 == GR_TYPE_CONCUSSION)
			sprint(self, PRINT_HIGH, "Concussion(");
		else if (self.tp_grenades_1 == GR_TYPE_ANTIGRAV)
			sprint(self, PRINT_HIGH, "AntiGrav(");
		else if (self.tp_grenades_1 == GR_TYPE_NAIL)
			sprint(self, PRINT_HIGH, "Nail(");
		else if (self.tp_grenades_1 == GR_TYPE_MIRV)
			sprint(self, PRINT_HIGH, "Mirv(");
		else if (self.tp_grenades_1 == GR_TYPE_NAPALM)
			sprint(self, PRINT_HIGH, "Napalm(");
		else if (self.tp_grenades_1 == GR_TYPE_FLARE)
			sprint(self, PRINT_HIGH, "Flare(");
		else if (self.tp_grenades_1 == GR_TYPE_GAS)
			sprint(self, PRINT_HIGH, "Hallucinogenic(");
		else if (self.tp_grenades_1 == GR_TYPE_EMP)
			sprint(self, PRINT_HIGH, "EMP(");
		else if (self.tp_grenades_1 == GR_TYPE_FLASH)
			sprint(self, PRINT_HIGH, "Flash(");
		else if (self.tp_grenades_1 == GR_TYPE_FRAG)
			sprint(self, PRINT_HIGH, "Frag(");
		else if (self.tp_grenades_1 == GR_TYPE_KRAC)
			sprint(self, PRINT_HIGH, "Krac(");
        else if (self.tp_grenades_1 == GR_TYPE_CALTROP)
			sprint(self, PRINT_HIGH, "Caltrop(");
		else if (self.tp_grenades_1 == GR_TYPE_BIO)
			sprint(self, PRINT_HIGH, "Biological(");
		else 
			sprint(self, PRINT_HIGH, "BUG(");

		ac = ftos(self.no_grenades_1);
		sprint(self, PRINT_HIGH, ac);
		sprint(self, PRINT_HIGH, ")\n");
	}
	if (self.no_grenades_2 > 0)
	{
		sprint(self, PRINT_HIGH, "Gren.Type 2: ");
		if (self.tp_grenades_2 == GR_TYPE_NORMAL)
			sprint(self, PRINT_HIGH, "Normal(");
		else if (self.tp_grenades_2 == GR_TYPE_CONCUSSION)
			sprint(self, PRINT_HIGH, "Concussion(");
		else if (self.tp_grenades_2 == GR_TYPE_NAIL)
			sprint(self, PRINT_HIGH, "Nail(");
		else if (self.tp_grenades_2 == GR_TYPE_ANTIGRAV)
			sprint(self, PRINT_HIGH, "AntiGrav(");
        else if (self.tp_grenades_2 == GR_TYPE_CALTROP)
			sprint(self, PRINT_HIGH, "Caltrop(");
        else if (self.tp_grenades_2 == GR_TYPE_MIRV)
        	sprint(self, PRINT_HIGH, "Mirv(");
        else if (self.tp_grenades_2 == GR_TYPE_BIO)
			sprint(self, PRINT_HIGH, "Biological(");
		else if (self.tp_grenades_2 == GR_TYPE_NAPALM)
			sprint(self, PRINT_HIGH, "Napalm(");
		else if (self.tp_grenades_2 == GR_TYPE_FLARE)
			sprint(self, PRINT_HIGH, "Flare(");
		else if (self.tp_grenades_2 == GR_TYPE_GAS)
			sprint(self, PRINT_HIGH, "Hallucinogenic(");
		else if (self.tp_grenades_2 == GR_TYPE_EMP)
			sprint(self, PRINT_HIGH, "EMP(");
		else if (self.tp_grenades_2 == GR_TYPE_FLASH)
			sprint(self, PRINT_HIGH, "Flash(");
		else if (self.tp_grenades_2 == GR_TYPE_FRAG)
			sprint(self, PRINT_HIGH, "Frag(");
		else if (self.tp_grenades_2 == GR_TYPE_KRAC)
			sprint(self, PRINT_HIGH, "Krac(");
 		else 
			sprint(self, PRINT_HIGH, "BUG(");

		ac = ftos(self.no_grenades_2);
		sprint(self, PRINT_HIGH, ac);
		sprint(self, PRINT_HIGH, ")\n");
	}


	// Scanner
	if (self.tf_items & NIT_SCANNER)
	{
		sprint(self, PRINT_HIGH, "Scanner. ");
		special = special + 1; //CH determines \n
	}
	if (self.cutf_items & CUTF_JAMMER)
	{
		sprint(self, PRINT_HIGH, "Jammer. ");
		special = special + 1; //CH determines \n
	}

	if (self.cutf_items & CUTF_CYBERAUG && !(self.weapons_carried & WEAP_MEDIKIT))
	{
		sprint(self, PRINT_HIGH, "CyberAug (");
		ac = ftos(self.ammo_medikit);
		sprint(self, PRINT_HIGH, ac);
		sprint(self, PRINT_HIGH, "). ");
		special = special + 1; //CH determines \n
	}
	else if (self.cutf_items & CUTF_CYBERAUG && self.weapons_carried & WEAP_MEDIKIT)
		sprint(self, PRINT_HIGH, "CyberAug/");
	// Medikit and ammo
	if (self.weapons_carried & WEAP_MEDIKIT)
	{
		sprint(self, PRINT_HIGH, "Medikit (");
		ac = ftos(self.ammo_medikit);
		sprint(self, PRINT_HIGH, ac);
		sprint(self, PRINT_HIGH, "). ");
		special = special + 1; //CH determines \n
	}

	//if (self.cutf_items & CUTF_INTERFACE)  //- OfN -
	//	sprint(self, PRINT_HIGH, "Cyber Interface. ");


	// Detpack
	if (self.cutf_items & CUTF_DETPACK)
	{
		if (self.ammo_detpack > 0)
		{
			ac = ftos(self.ammo_detpack);

			sprint(self, PRINT_HIGH, ac);
			sprint(self, PRINT_HIGH, " Detpack");
			if (self.ammo_detpack > 1)
				sprint(self, PRINT_HIGH, "s");
			sprint(self, PRINT_HIGH, ". ");
			special = special + 1; //CH determines \n
		}
	}
	if (self.cutf_items & CUTF_TOSSABLEDET)
	{
		if (self.ammo_c4det > 0)
		{
			ac = ftos(self.ammo_c4det);

			sprint(self, PRINT_HIGH, ac);
			sprint(self, PRINT_HIGH, " Tossable Detpack");
			if (self.ammo_c4det > 1)
				sprint(self, PRINT_HIGH, "s");
			sprint(self, PRINT_HIGH, ". ");
			special = special + 1; //CH determines \n
		}
	}

	// GoalItems
	tg = find (NIL, classname, "item_tfgoal");
	while (tg)
	{
		if (tg.owner == self)
		{
			sprint(self, PRINT_HIGH, tg.netname);
			sprint(self, PRINT_HIGH, ". ");
			special = special + 1; //CH determines \n
		}

		tg = find(tg, classname, "item_tfgoal");
	}

	// Armor
	if (self.armorvalue > 0)
	{
		special = special + TeamFortress_DescribeArmor(self, self.armorclass);
	}
if (special > 0)
	sprint(self, PRINT_HIGH, "\n");

if (!invis_only)
{
	// Spy gets told what skin and color he/she is wearing
	if ((self.cutf_items & CUTF_SPY_KIT) && invis_only == FALSE)
	{
		sprint (self, PRINT_HIGH, "Skin : ");
		if (self.undercover_skin != 0)
			TeamFortress_PrintClassName(self,self.undercover_skin,0);
		else
			TeamFortress_PrintClassName(self,self.skin,0);

		sprint (self, PRINT_HIGH, "Colors : Team ");
		if (self.undercover_team != 0)
			ac = ftos(self.undercover_team);
		else
			ac = ftos(self.team_no);
		sprint (self, PRINT_HIGH, ac);
		sprint(self, PRINT_HIGH, "\n");
	}
}

	//WK Let us know if we have a guy summoned
	if (self.job & JOB_DEMON_OUT)
	{
		if (self.job & JOB_ARMY)
            ac="soldier";
        else if (self.job & JOB_WARLOCK)
            ac=GetMonsterName(self.demon_two);

        sprint (self, PRINT_HIGH, "Your ");
        sprint (self, PRINT_HIGH, ac);
        sprint(self, PRINT_HIGH," has ");

        ac = ftos(ceil(self.demon_one.health));
        sprint (self, PRINT_HIGH, ac);
        sprint (self, PRINT_HIGH, "�");
        ac = ftos(ceil(self.demon_one.max_health));
        sprint (self, PRINT_HIGH, ac);
        sprint (self, PRINT_HIGH, " HP\n");
    }

    if (self.has_sentry)
    {
        tg = find(NIL, classname, "building_sentrygun");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, "������: ");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, "�");
				ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, ac);
                sprint (self, PRINT_HIGH, " ��\n");

			}
			tg = find(tg, classname, "building_sentrygun");
		}
    }
    if (self.has_tesla)
    {
        tg = find(NIL, classname, "building_tesla");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, "�����: ");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, "�");
				ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, ac);
                sprint (self, PRINT_HIGH, " ��\n");

			}
			tg = find(tg, classname, "building_tesla");
		}
    }
    if (self.has_dispenser)
    {
        tg = find(NIL, classname, "building_dispenser");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, "���������: ");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, "�");
				ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, ac);
                sprint (self, PRINT_HIGH, " ��\n");

			}
			tg = find(tg, classname, "building_dispenser");
		}
    }
    if (self.has_sensor)
    {
        tg = find(NIL, classname, "building_sensor");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, "������: ");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, "�");
				ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, ac);
                sprint (self, PRINT_HIGH, " ��\n");

			}
			tg = find(tg, classname, "building_sensor");
		}
    }
    if (self.has_camera)
    {
        tg = find(NIL, classname, "building_camera");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, "������: ");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, "�");
				ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, ac);
                sprint (self, PRINT_HIGH, " ��\n");

			}
			tg = find(tg, classname, "building_camera");
		}
    }
    if (self.has_teleporter > 0)
    {
        tg = find(NIL, classname, "building_teleporter");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, "����������: ");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, "�");
				ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, ac);
                sprint (self, PRINT_HIGH, " ��\n");

			}
			tg = find(tg, classname, "building_teleporter");
		}
    }
    if (self.has_fieldgen > 0)
    {
        tg = find(NIL, classname, "building_fieldgen");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, "����� ���������: ");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, "�");
				ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, ac);
                sprint (self, PRINT_HIGH, " ��\n");

			}
			tg = find(tg, classname, "building_fieldgen");
		}
    }

    /*if (self.job & JOB_WARLOCK && self.job & JOB_DEMON_OUT)
	{
		sprint (self, PRINT_HIGH, "You have a ");
        ac=GetMonsterName(self.demon_two);
        sprint (self, PRINT_HIGH, ac);
        sprint (self, PRINT_HIGH, " summoned: ");

		tg = find(NIL, classname, "monster_demon1");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				//sprint (self, PRINT_HIGH, " (");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, " HP ");
			}
			tg = find(tg, classname, "monster_demon1");
		}
		
		tg = find(NIL, classname, "monster_army");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				sprint (self, PRINT_HIGH, " (");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, ") ");
			}
			tg = find(tg, classname, "monster_army");
		}

		tg = find(NIL, classname, "monster_shambler");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				//sprint (self, PRINT_HIGH, " (");
				sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, " HP ");
			}
			tg = find(tg, classname, "monster_shambler");
		}

		tg = find(NIL, classname, "monster_wizard");
		while (tg)
		{
			if (tg.real_owner == self)
			{
				ac = ftos(ceil(tg.health));
				//sprint (self, PRINT_HIGH, " (");
				sprint (self, PRINT_HIGH, ac);
                ac = ftos(ceil(tg.max_health));
                sprint (self, PRINT_HIGH, "�");
                sprint (self, PRINT_HIGH, ac);
				sprint (self, PRINT_HIGH, " HP ");
			}
			tg = find(tg, classname, "monster_wizard");
		}

		//sprint (self, PRINT_HIGH, ac);
		sprint (self, PRINT_HIGH, "\n");
	}*/
	
    /*if (self.job & JOB_WARLOCK) // they can see that on warlock menu
	{
		ac = ftos (self.demon_blood);
		sprint (self, PRINT_HIGH, "Knife kills: ", ac, "\n");  // knife kills
	}*/    

    //CH if you have boots, state percent of fuel
	if (self.tf_items & NIT_HOVER_BOOTS)
	{
		if (self.hover_time <= 0)
			ac = "0";
		else
			ac = ftos(floor(100 * (self.hover_time / MAX_HOVER_FUEL)));
		sprint (self, PRINT_HIGH, "Boot Charge: ");
		sprint (self, PRINT_HIGH, ac);
		sprint (self, PRINT_HIGH, "%  ");
	}
	//CH if you have a job.  tell when can work
	if (self.job & JOB_ALL)
	{
		if ((self.job_finished - time) <= 0)
			sprint (self,PRINT_HIGH, "Skill Time: ");
		else
		{
			ac = ftos(ceil(self.job_finished - time));
		sprint (self,PRINT_HIGH, "Skill Time:");
		sprint (self, PRINT_HIGH, ac);
		if (ceil(self.job_finished - time) == 1)
			sprint (self, PRINT_HIGH, " second");
		else
			sprint (self, PRINT_HIGH, " seconds");
		}
	}

    if (self.aura) //- OfN - If we have an aura it should tell
    {
        if (self.crusader_inspirator && !(self.crusader_inspirator.has_disconnected) && self.crusader_inspirator.classname == "player")
        {
            sprint(self,PRINT_HIGH,"\n");
            sprint(self,PRINT_HIGH,self.crusader_inspirator.netname);
            sprint(self,PRINT_HIGH," grants you the AURA of ");
        }
        else
            sprint(self,PRINT_HIGH,"\nYou enjoy the AURA of ");
        
        if (self.aura == AURA_POWER)
            sprint(self,PRINT_HIGH," �����.");
        else if (self.aura == AURA_RESISTANCE)
            sprint(self,PRINT_HIGH," ����������.");
        else if (self.aura == AURA_HASTE)
            sprint(self,PRINT_HIGH," �����.");
        else if (self.aura == AURA_INVIS)
            sprint(self,PRINT_HIGH," ������������.");
    }

	sprint (self, PRINT_HIGH, "\n");
};

//=========================================================================
// Displays the state of the ToggleFlags
void() TeamFortress_ShowTF =
{
	local string st;

	// Class Persistence between lvls On/Off
	if (toggleflags & TFLAG_CLASS_PERSIST)
		sprint (self, PRINT_HIGH, "Class Persistence On.\n");
	else
		sprint (self, PRINT_HIGH, "Class Persistence Off.\n");

	// Cheat Checking On/Off
	if (toggleflags & TFLAG_CHEATCHECK)
		sprint (self, PRINT_HIGH, "Cheat Checking On.\n");
	else
		sprint (self, PRINT_HIGH, "Cheat Checking Off.\n");

	// AutoTeam On/Off
	if (toggleflags & TFLAG_AUTOTEAM)
		sprint (self, PRINT_HIGH, "AutoTeam On.\n");
	else
		sprint (self, PRINT_HIGH, "AutoTeam Off.\n");

	// RespawnDelay
	if (toggleflags & TFLAG_RESPAWNDELAY)
		st = ftos(respawn_delay_time);
	else
		st = "No";
	sprint (self, PRINT_HIGH, st);
	if (st != "No")
		sprint (self, PRINT_HIGH, " second");
	sprint (self, PRINT_HIGH, " Respawn Delay.\n");

	// TeamFrags On/Off
	if (toggleflags & TFLAG_TEAMFRAGS)
		sprint (self, PRINT_HIGH, "TeamFrags On.\n");
	else
		sprint (self, PRINT_HIGH, "TeamFrags Off.\n");

	// Grapple hook
	if (allow_hook)
		sprint (self, PRINT_HIGH, "Grapple On.\n");
	else
		sprint (self, PRINT_HIGH, "Grapple Off.\n");

};

void() TeamFortress_GrenadePrimed;

//=========================================================================
// Primes a grenade of the type corresponding to the player's impulse
void() TeamFortress_PrimeGrenade =
{
	local float gtype = GR_TYPE_NONE;
	local string gs, ptime;
	local entity tGrenade;

	/*if (self.job & JOB_THIEF && self.job & JOB_FULL_HIDE) {
		sprint(self,PRINT_HIGH,"You can't throw grens while invisible\n");
		return;
	}*/

	// If you've already primed a grenade, return
	if ((self.tfstate & TFSTATE_GRENPRIMED) || (self.tfstate & TFSTATE_GRENTHROWING))
	{
		return;
	}

	if (self.impulse == TF_GRENADE_1)
	{
#define SPAM_TIME 7
		//WK Stop frag spammming // enabled again
		if (self.tp_grenades_1 == GR_TYPE_FRAG && self.no_grenades_1 > 0) {
			if ((self.team_no == 1 && team1nextspam >= time) ||
	 	          (self.team_no == 2 && team2nextspam >= time) ||
                      (self.team_no == 3 && team3nextspam >= time) ||
			    (self.team_no == 4 && team4nextspam >= time)) {
				sprint(self,PRINT_HIGH,"Your team already has a spam grenade in the world.\n");
				return;
			}
			if (self.team_no == 1) team1nextspam = time + SPAM_TIME;
			if (self.team_no == 2) team2nextspam = time + SPAM_TIME;
                  if (self.team_no == 3) team3nextspam = time + SPAM_TIME;
			if (self.team_no == 4) team4nextspam = time + SPAM_TIME;
			
		} // OfN Removed spam control // enabled again
		gtype = self.tp_grenades_1;
		if (gtype == GR_TYPE_CONCUSSION)
			gs = "Concussion grenade";
		else if (gtype == GR_TYPE_ANTIGRAV)
			gs = "AntiGrav grenade";
        else if (gtype == GR_TYPE_BIO)
			gs = "BioInfection grenade";
   		else if (gtype == GR_TYPE_CALTROP)
			gs = "Caltrop grenade";
		else if (gtype == GR_TYPE_NAIL)
			gs = "Nail grenade";
		else if (gtype == GR_TYPE_MIRV)
			gs = "Mirv grenade";
		else if (gtype == GR_TYPE_NAPALM)
			gs = "Napalm grenade";
		else if (gtype == GR_TYPE_FLARE)
			gs = "Flare";
		else if (gtype == GR_TYPE_GAS)
			gs = "Gas grenade";
		else if (gtype == GR_TYPE_EMP)
			gs = "EMP grenade";
		else if (gtype == GR_TYPE_FLASH)
			gs = "Flash grenade";
		else if (gtype == GR_TYPE_FRAG)
			gs = "Fragmentation grenade";
		else if (gtype == GR_TYPE_KRAC)
			gs = "Krac grenade";
		else
			gs = "Grenade";

		if (self.no_grenades_1 >= 1)
		{
			ptime = ftos( GR_PRIMETIME );

			sprint(self, PRINT_HIGH, gs);
			sprint(self, PRINT_HIGH, " primed, ");
			sprint(self, PRINT_HIGH, ptime);
			sprint(self, PRINT_HIGH, " seconds...\n");

			/*if ((self.tp_grenades_1 == GR_TYPE_NAIL || self.tp_grenades_1 == GR_TYPE_FRAG) && self.no_grenades_1 > 2)
				self.no_grenades_1 = 2;*/

            if (self.no_grenades_1 > GetMaxGrens(self,1))
                self.no_grenades_1 = GetMaxGrens(self,1);


			self.no_grenades_1 = self.no_grenades_1 - 1;

            // OfN 
            //sound(self, CHAN_MISC, "weapons/pinpull.wav", 1, ATTN_IDLE);
		}
		else
		{
			sprint(self, PRINT_HIGH, "No ");
			sprint(self, PRINT_HIGH, gs);
			sprint(self, PRINT_HIGH, "s left.\n");
			return;
		}
	}
	if (self.impulse == TF_GRENADE_2)
	{
		if (self.tp_grenades_2 == GR_TYPE_FRAG  && self.no_grenades_2 > 0) {
			if ((self.team_no == 1 && team1nextspam >= time) ||
			    (self.team_no == 2 && team2nextspam >= time) ||
                      (self.team_no == 3 && team3nextspam >= time) ||
			    (self.team_no == 4 && team4nextspam >= time)) {
				sprint(self,PRINT_HIGH,"Your team already has a spam grenade in the world.\n");
				return;
			}
			if (self.team_no == 1) team1nextspam = time + SPAM_TIME + 1;
			if (self.team_no == 2) team2nextspam = time + SPAM_TIME + 1;
			if (self.team_no == 3) team3nextspam = time + SPAM_TIME + 1;
			if (self.team_no == 4) team4nextspam = time + SPAM_TIME + 1;
			
		} // OfN Removed spam control
		gtype = self.tp_grenades_2;
		if (gtype == GR_TYPE_CONCUSSION)
			gs = "Concussion grenade";
		else if (gtype == GR_TYPE_ANTIGRAV)
			gs = "AntiGrav grenade";
        else if (gtype == GR_TYPE_BIO)
			gs = "BioInfection grenade";
   		else if (gtype == GR_TYPE_CALTROP)
			gs = "Caltrop grenade";
		else if (gtype == GR_TYPE_NAIL)
			gs = "Nail grenade";
		else if (gtype == GR_TYPE_MIRV)
			gs = "Mirv grenade";
		else if (gtype == GR_TYPE_NAPALM)
			gs = "Napalm grenade";
		else if (gtype == GR_TYPE_FLARE)
			gs = "Flare";
		else if (gtype == GR_TYPE_GAS)
			gs = "Gas grenade";
		else if (gtype == GR_TYPE_EMP)
			gs = "EMP grenade";
		else if (gtype == GR_TYPE_FLASH)
			gs = "Flash grenade";
		else if (gtype == GR_TYPE_FRAG)
			gs = "Fragmentation grenade";
		else if (gtype == GR_TYPE_KRAC)
			gs = "Krac grenade";
		else
			gs = "Grenade";

        
/*        if (gtype == GR_TYPE_CONCUSSION)
			gs = "Concussion grenade";
		else if (gtype == GR_TYPE_NAIL)
			gs = "Nail grenade";
		else if (gtype == GR_TYPE_MIRV)
			gs = "Mirv grenade";
		else if (gtype == GR_TYPE_NAPALM)
			gs = "Napalm grenade";
		else if (gtype == GR_TYPE_FLARE)
			gs = "Flare";
		else if (gtype == GR_TYPE_GAS)
			gs = "Gas grenade";
		else if (gtype == GR_TYPE_EMP)
			gs = "EMP grenade";
		else if (gtype == GR_TYPE_FLASH)
			gs = "Flash grenade";
		else if (gtype == GR_TYPE_FRAG)
			gs = "Fragmentation grenade";
        else if (gtype == GR_TYPE_BIO)
			gs = "BioInfection grenade";
   		else if (gtype == GR_TYPE_CALTROP)
			gs = "Caltrop grenade";

		else if (gtype == GR_TYPE_KRAC)
			gs = "Krac grenade";
		else
			gs = "Grenade";*/

		if (self.no_grenades_2 >= 1)
		{
			ptime = ftos( GR_PRIMETIME );

			sprint(self, PRINT_HIGH, gs);
			sprint(self, PRINT_HIGH, " primed, ");
			sprint(self, PRINT_HIGH, ptime);
			sprint(self, PRINT_HIGH, " seconds...\n");

			//WK Limit Nail grenades to 2 - ofn and frag
			
            if (self.no_grenades_2 > GetMaxGrens(self,2))
                self.no_grenades_2 = GetMaxGrens(self,2);

            /*if ((self.tp_grenades_2 == GR_TYPE_NAIL || self.tp_grenades_2 == GR_TYPE_FRAG) && self.no_grenades_2 > 2)
				self.no_grenades_2 = 2;*/

			self.no_grenades_2 = self.no_grenades_2 - 1;

            //sound(self, CHAN_MISC, "weapons/pinpull.wav", 1, ATTN_IDLE);
		}
		else
		{
			sprint(self, PRINT_HIGH, "No ");
			sprint(self, PRINT_HIGH, gs);
			sprint(self, PRINT_HIGH, "s left.\n");
			return;
		}
	}

	self.tfstate = (self.tfstate | TFSTATE_GRENPRIMED);
	tGrenade = spawn();
	tGrenade.owner = self;
	tGrenade.weapon = gtype;
	//tGrenade.classname = "timer"; //Ofn was comented, bug? - IT SHOULD BE COMMENTED :)
	tGrenade.nextthink = time + 0.8;
	tGrenade.heat = time + GR_PRIMETIME + 0.8;
	tGrenade.think = TeamFortress_GrenadePrimed;
    if (gtype == GR_TYPE_CALTROP)
		tGrenade.heat = tGrenade.heat - GR_PRIMETIME;
};

void() TeamFortress_GrenadePrimed =
{
	local entity user;
	local entity oldself;

	user = self.owner;

	if (!(user.tfstate & TFSTATE_GRENTHROWING) && !user.deadflag)
	{
		self.nextthink = time + 0.1;

		if (!self.think)
			dremove(self);
		
		if (time > self.heat)
			TeamFortress_ExplodePerson();

		return;
	}

	if (!(user.tfstate & TFSTATE_GRENPRIMED))
	{
		RPrint("GrenadePrimed logic error\n");
	}

	user.tfstate = user.tfstate - (user.tfstate & TFSTATE_GRENPRIMED);
	user.tfstate = user.tfstate - (user.tfstate & TFSTATE_GRENTHROWING);

    // ofn
    if (self.weapon == GR_TYPE_FLARE)
        sound (user, CHAN_WEAPON, "weapons/flmfire2.wav", 1, ATTN_NORM);
    else
        sound (user, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
        //sound (user, CHAN_WEAPON, "weapons/throw.wav", 1, ATTN_NORM);

	KickPlayer(-1, user);
	newmis = spawn ();
	newmis.owner = user;
	newmis.movetype = MOVETYPE_BOUNCE;
	newmis.solid = SOLID_BBOX;
	newmis.classname = "grenade";
	
	// set grenade speed
	makevectors (user.v_angle);

	if (user.deadflag)
	{
		// if user is dead, throw grenade directly up
		newmis.velocity = '0 0 200';
	}
	else
	{
		if (user.v_angle_x)
		{
			newmis.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
		}
		else
		{
			newmis.velocity = aim(user, 10000);
			newmis.velocity = newmis.velocity * 600;
			newmis.velocity_z = 200;
		}
	}

	newmis.angles = vectoangles(newmis.velocity);

	// set the grenade's thinktime to when the PRIMETIME runs out
	newmis.think = dont_think;
	newmis.nextthink = self.heat;

	// set the think and touches to the appropriate grenade type
	if (self.weapon == GR_TYPE_NORMAL)
	{
		newmis.touch = NormalGrenadeTouch;
		newmis.think = NormalGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");

	}
	else if (self.weapon == GR_TYPE_CONCUSSION)
	{
		newmis.touch = ConcussionGrenadeTouch;
		newmis.think = ConcussionGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
	else if (self.weapon == GR_TYPE_BIO)
	{
		newmis.touch = BioGrenadeTouch;
		newmis.think = BioGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
    else if (self.weapon == GR_TYPE_CALTROP)
	{
		newmis.touch = NIL;
		newmis.think = CaltropGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '0 0 0';
		newmis.velocity = '0 0 0';
		setmodel (newmis, "");
	}
    else if (self.weapon == GR_TYPE_ANTIGRAV)
	{
		newmis.touch = ConcussionGrenadeTouch;
		newmis.think = AntiGravGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
	else if (self.weapon == GR_TYPE_NAIL)
	{
		newmis.touch = NailGrenadeTouch;
		newmis.think = NailGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '0 300 0';
		setmodel (newmis, "progs/biggren.mdl");
	}
	else if (self.weapon == GR_TYPE_MIRV)
	{
		newmis.touch = MirvGrenadeTouch;
		newmis.think = MirvGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '0 300 0';
		setmodel (newmis, "progs/biggren.mdl");
	}
	else if (self.weapon == GR_TYPE_NAPALM)
	{
		newmis.touch = NapalmGrenadeTouch;
		newmis.think = NapalmGrenadeExplode;
		newmis.skin = 2;
		newmis.avelocity = '100 300 100';
		setmodel (newmis, "progs/biggren.mdl");
	}
//CH flares no longer used
	else if (self.weapon == GR_TYPE_FLARE)
	{
		newmis.movetype = MOVETYPE_FLY;
        newmis.touch = FlareGrenadeTouch;
		newmis.think = FlareGrenadeExplode;
		//newmis.skin  = 0;//TF_FLARE_OFF;
		newmis.avelocity = '0 0 0';
        

        makevectors (user.v_angle);
	    newmis.velocity = v_forward;
        //newmis.velocity = aim(user, 10000);
    	newmis.velocity = newmis.velocity * 2000;
        
//        newmis.velocity = newmis.velocity * 4;
        //newmis.velocity_z = 0;
		setmodel (newmis, "progs/flarefly.mdl");
        newmis.skin=0;
        newmis.has_holo=0; //flag turned on when explodes
	}
	else if (self.weapon == GR_TYPE_GAS)
	{
		newmis.touch = GasGrenadeTouch;
		newmis.think = GasGrenadeExplode;
		newmis.skin = 3;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/grenade2.mdl");
	}
	else if (self.weapon == GR_TYPE_EMP)
	{
		newmis.touch = EMPGrenadeTouch;
		newmis.think = EMPGrenadeExplode;
		newmis.skin = 4;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/grenade2.mdl");
	}
	else if (self.weapon == GR_TYPE_FLASH)
	{
		newmis.touch = FlashGrenadeTouch;
		newmis.think = FlashGrenadeExplode;
		newmis.skin = 2;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
//WK New Grenades
	else if (self.weapon == GR_TYPE_FRAG)
	{
		newmis.touch = FragGrenadeTouch;
		newmis.think = FragGrenadeExplode;
		newmis.skin = 0; //WK Green Skin
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
	else if (self.weapon == GR_TYPE_KRAC)
	{
		newmis.touch = KracGrenadeTouch;
		newmis.think = KracGrenadeExplode;
		newmis.skin = 1; //WK Conc skin
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}

	setsize (newmis, '0 0 0', '0 0 0');		
	setorigin (newmis, user.origin);

    // OfN
    if (self.weapon == GR_TYPE_FLARE)
	{
      setorigin (newmis, user.origin + '0 0 16');
    }

	oldself = self;
	self = self.owner;

#ifdef DEMO_STUFF
	if (live_camera)
		CamProjectileLockOn();
#endif

	self = oldself;

	// Remove primed grenade object	
	dremove(self);
};

//=========================================================================
// Throws a currently primed grenade
void() TeamFortress_ThrowGrenade =
{
	// If no grenade is primed, return
	if (!(self.tfstate & TFSTATE_GRENPRIMED))
		return;

	//WK Tossing a gren reveals yourself (so people don't spam)
	//if (self.job & JOB_THIEF && (self.job & JOB_ACTIVE || self.job & JOB_FULL_HIDE))
	if (self.job & JOB_THIEF && self.job & JOB_FULL_HIDE)
		RevealThief(self,FALSE);

	self.tfstate = self.tfstate | TFSTATE_GRENTHROWING;
};

//=========================================================================
// PLAYER CLASS HANDLING FUNCTIONS
//=========================================================================
// Return TRUE is this class is allowed on this map
float(float pc) IsLegalClass =
{
	local float bit = 0;

	// Spy may be turned off
	if (spy_off == TRUE && pc == PC_SPY)
		return FALSE;

	if (pc == PC_SCOUT)
		bit = TF_ILL_SCOUT;
	else if (pc == PC_SNIPER)
		bit = TF_ILL_SNIPER;
	else if (pc == PC_SOLDIER)
		bit = TF_ILL_SOLDIER;
	else if (pc == PC_DEMOMAN)
		bit = TF_ILL_DEMOMAN;
	else if (pc == PC_MEDIC)
		bit = TF_ILL_MEDIC;
	else if (pc == PC_HVYWEAP)
		bit = TF_ILL_HVYWEP;
	else if (pc == PC_PYRO)
		bit = TF_ILL_PYRO;
	else if (pc == PC_SPY)
		bit = TF_ILL_SPY;
	else if (pc == PC_ENGINEER)
		bit = TF_ILL_ENGINEER;
	else if (pc == PC_RANDOM)
//WK	else if (pc == PC_RANDOM || pc == PC_CUSTOM) //WK Disabling randompc disables //WK customclass
		bit = TF_ILL_RANDOMPC;

	if ((illegalclasses & bit) || (TeamFortress_TeamGetIllegalClasses(self.team_no) & bit))
		return FALSE;

	return TRUE;
};

//=========================================================================
// Alter the player's Movement based on class
void(entity p) TeamFortress_SetSpeed =
{
	local float tf;
	local entity te;
	local float ms = p.maxspeed;

	//stuffcmd(p,"cl_movespeedkey 1\n");

	makeImmune(self,time + 1.1); //WK Don't boot someone decelerating

    // - OfN -//
    //-----------------------------------------------------------------------//
    // STOP THAT SILLY DAMN BUGS, SPY SLIDING ETC.. !!!!!!!!!!!!!!!!!!!!!!! -//
    if (p.is_feigning || p.is_haxxxoring || p.is_detpacking || p.is_building)
        p.tfstate = p.tfstate | TFSTATE_CANT_MOVE;
    //-----------------------------------------------------------------------//

	// Check for any reason why they can't move at all
	if (p.tfstate & TFSTATE_CANT_MOVE) {
		if (STOP_MOUSE_MOVEMENT == ON) {
			stuffcmd(p,"m_forward 0\n");
			stuffcmd(p,"m_side 0\n");
		}

		p.velocity = '0 0 0';
		stuffcmd(p,"cl_backspeed 0\n");
		stuffcmd(p,"cl_forwardspeed 0\n");
		stuffcmd(p,"cl_sidespeed 0\n");
		p.maxspeed = 0;
		return;
	} else {
		if (STOP_MOUSE_MOVEMENT == ON) {
			stuffcmd(p,"m_forward 1\n");
			stuffcmd(p,"m_side 0.8\n");
		}
	}

	// First, get their max class speed
	// WK We don't use this block much any more
	if ( p.playerclass == PC_SCOUT)
		p.maxspeed = PC_SCOUT_MAXSPEED;
	else if ( p.playerclass == PC_SNIPER)
		p.maxspeed = PC_SNIPER_MAXSPEED;
	else if ( p.playerclass == PC_SOLDIER)
		p.maxspeed = PC_SOLDIER_MAXSPEED;
	else if ( p.playerclass == PC_DEMOMAN)
		p.maxspeed = PC_DEMOMAN_MAXSPEED;
	else if ( p.playerclass == PC_MEDIC)
		p.maxspeed = PC_MEDIC_MAXSPEED;
	else if ( p.playerclass == PC_HVYWEAP)
		p.maxspeed = PC_HVYWEAP_MAXSPEED;
	else if ( p.playerclass == PC_PYRO)
		p.maxspeed = PC_PYRO_MAXSPEED;
	else if ( p.playerclass == PC_CIVILIAN)
		p.maxspeed = PC_CIVILIAN_MAXSPEED;
	else if ( p.playerclass == PC_SPY)
		p.maxspeed = PC_SPY_MAXSPEED;
	else if ( p.playerclass == PC_ENGINEER)
		p.maxspeed = PC_ENGINEER_MAXSPEED;
	else if ( p.playerclass == PC_UNDEFINED)
		p.maxspeed = 320;
	else if ( p.playerclass == PC_CUSTOM) {
		p.maxspeed = p.custom_speed;
		if (p.done_custom & CUSTOM_BUILDING) //We are building a class
			p.maxspeed = 0;
	}

	if (p.playerclass != PC_UNDEFINED) {
		//1st if we have scuba gear ...
		if (p.tf_items & NIT_SCUBA) {
			if (p.flags & FL_INWATER)	// and are underwater, increase speed
				p.maxspeed = p.maxspeed + 200;
			else						//Fins slow us down out of water
				p.maxspeed = p.maxspeed - 20;
		}

		// 2nd, see if any GoalItems are slowing them down
		tf = 0;
		te = find (NIL, classname, "item_tfgoal");
		while ((te) && (tf == 0)) {
			if (te.owner == p) {
				if (te.goal_activation & TFGI_SLOW) {
					tf = 1;
					p.maxspeed = p.maxspeed / 2;
				}
			}
			te = find(te, classname, "item_tfgoal");
		}

		// 3rd, See if they're tranquilised
		if (p.tfstate & TFSTATE_TRANQUILISED) {
			//WK p.maxspeed = (p.maxspeed / 3) * 2;
			if (p.maxspeed > 170)
				p.maxspeed = 170;
		}
		
		if (p.tfstate & TFSTATE_C4THROW)
			p.maxspeed = p.maxspeed / 3;

		// 4th, check for leg wounds
		if (p.leg_damage) {
			if (p.leg_damage > 9)
				p.leg_damage = 9;

			// reduce speed by 10% per leg wound
			p.maxspeed = (p.maxspeed * ((10 - p.leg_damage) / 10));
		}

		// 5th, if they're a sniper, and they're aiming, halve their speed
		// again, but not to less than 60
		if (p.tfstate & TFSTATE_AIMING) {
			if (p.maxspeed > 120)
				p.maxspeed = p.maxspeed / 2;
			else if (p.maxspeed > 60)
				p.maxspeed = 60;
		}

		// WK 6th, See if they're partially hidden
		if (p.job & JOB_THIEF) {
			if (p.job & JOB_ACTIVE)
				p.maxspeed = (p.maxspeed * 3) / 4;
			else if (p.job & JOB_FULL_HIDE)
				if (p.maxspeed > 130)
					p.maxspeed = 130;
		}

		//WK 7th, Check to see if they are sprinting or recovering
		//Note that tired is both ACTIVE and TIRED
		if (p.job & JOB_RUNNER) {
			if (p.job & JOB_TIRED)
				p.maxspeed = 2 * p.maxspeed / 3;
			else if (p.job & JOB_ACTIVE)
				p.maxspeed = p.maxspeed + 200;
		}

		// 8th, check if they're firing an Assault Cannon
		if (p.tfstate & TFSTATE_ASSAULTCANNON)
			p.maxspeed /= 4;
	}

	if (p.maxspeed != ms) {
		local string speed = ftos (p.maxspeed);
		stuffcmd(p,"cl_backspeed " + speed + "\n");
		stuffcmd(p,"cl_forwardspeed " + speed + "\n");
		stuffcmd(p,"cl_sidespeed " + speed + "\n");
	}
};

//=========================================================================
// Set the max_health of a player based on his/her class
void() TeamFortress_SetHealth = 
{
	if ( self.playerclass == PC_SCOUT )
		self.max_health = PC_SCOUT_MAXHEALTH;
	else if ( self.playerclass == PC_SNIPER )
		self.max_health = PC_SNIPER_MAXHEALTH;
	else if ( self.playerclass == PC_SOLDIER )
		self.max_health = PC_SOLDIER_MAXHEALTH;
	else if ( self.playerclass == PC_DEMOMAN )
		self.max_health = PC_DEMOMAN_MAXHEALTH;
	else if ( self.playerclass == PC_MEDIC )
		self.max_health = PC_MEDIC_MAXHEALTH;
	else if ( self.playerclass == PC_HVYWEAP )
		self.max_health = PC_HVYWEAP_MAXHEALTH;
	else if ( self.playerclass == PC_PYRO )
		self.max_health = PC_PYRO_MAXHEALTH;
	else if ( self.playerclass == PC_CIVILIAN )
		self.max_health = PC_CIVILIAN_MAXHEALTH;
	else if ( self.playerclass == PC_SPY )
		self.max_health = PC_SPY_MAXHEALTH;
	else if ( self.playerclass == PC_ENGINEER )
		self.max_health = PC_ENGINEER_MAXHEALTH;
	else if ( self.playerclass == PC_UNDEFINED )
	{
		self.max_health = 1; 
		self.takedamage = 0; // Prevent damage to PC_UNDEFINED players
	}

	self.health = self.max_health;
};
//==================================================
//CH returns value for skin.  used here and tfortmap.qc
float(entity p) Return_Custom_Skins =
{
	if (p.weapons_carried & WEAP_SNIPER_RIFLE)
		return PC_SNIPER;
	else if (p.weapons_carried & WEAP_ASSAULT_CANNON)
		return PC_HVYWEAP;
	else if (p.weapons_carried & WEAP_ROCKET_LAUNCHER)
		return PC_SOLDIER;
	else if (p.weapons_carried & WEAP_FLAMETHROWER)
		return PC_PYRO;
	else if (p.weapons_carried & WEAP_GRENADE_LAUNCHER)
		return PC_DEMOMAN;
	else if (p.weapons_carried & WEAP_MEDIKIT)
		return PC_MEDIC;
	else if (p.weapons_carried & WEAP_SPANNER)
		return PC_ENGINEER;
	else if (p.weapons_carried & WEAP_NAILGUN)
		return PC_SCOUT;
	else if (p.job & JOB_GUERILLA)
		return PC_DEMOMAN;
	else if (p.custom_speed > 320 || p.job & JOB_RUNNER)
		return PC_SCOUT;
	else if (p.cutf_items & CUTF_SPY_KIT)
		return PC_SPY;
	else if (p.cutf_items & CUTF_SENTRYGUN || p.tf_items & NIT_TESLA)
		return PC_ENGINEER;
	else
		return PC_SOLDIER;
};
//=========================================================================
// Set the skin of a player based on his/her class, if Classkin is on
void(entity p) TeamFortress_SetSkin = 
{
	local string st;

	makeImmune(self,time + 4);
	//self.immune_to_check = time + 4;


	if ((p.cutf_items & CUTF_SPY_KIT) && p.undercover_skin != 0)
		p.skin = p.undercover_skin;
	else
		p.skin = p.playerclass;

	st = "base"; // just in case

	if (p.skin != PC_UNDEFINED)
	{
	//WK Figure out what Mr.Custom Should look like
		if (p.playerclass == PC_CUSTOM && p.undercover_skin == 0)
		{
			p.skin = Return_Custom_Skins(p); //CH
		}

		if ( p.team_no == 4)
		{
			if ( p.skin == PC_SCOUT )
				st = TEAM4_SCOUT_SKIN;
			else if ( p.skin == PC_SNIPER )
				st = TEAM4_SNIPER_SKIN;
			else if ( p.skin == PC_SOLDIER )
				st = TEAM4_SOLDIER_SKIN;
			else if ( p.skin == PC_DEMOMAN )
				st = TEAM4_DEMOMAN_SKIN;
			else if ( p.skin == PC_MEDIC )
				st = TEAM4_MEDIC_SKIN;
			else if ( p.skin == PC_HVYWEAP )
				st = TEAM4_HVYWEAP_SKIN;
			else if ( p.skin == PC_PYRO )
				st = TEAM4_PYRO_SKIN;
			else if ( p.skin == PC_SPY )
				st = TEAM4_SPY_SKIN;
			else if ( p.skin == PC_ENGINEER )
				st = TEAM4_ENGINEER_SKIN;
		}
		else if ( p.team_no == 3)
		{
			if ( p.skin == PC_SCOUT )
				st = TEAM3_SCOUT_SKIN;
			else if ( p.skin == PC_SNIPER )
				st = TEAM3_SNIPER_SKIN;
			else if ( p.skin == PC_SOLDIER )
				st = TEAM3_SOLDIER_SKIN;
			else if ( p.skin == PC_DEMOMAN )
				st = TEAM3_DEMOMAN_SKIN;
			else if ( p.skin == PC_MEDIC )
				st = TEAM3_MEDIC_SKIN;
			else if ( p.skin == PC_HVYWEAP )
				st = TEAM3_HVYWEAP_SKIN;
			else if ( p.skin == PC_PYRO )
				st = TEAM3_PYRO_SKIN;
			else if ( p.skin == PC_SPY )
				st = TEAM3_SPY_SKIN;
			else if ( p.skin == PC_ENGINEER )
				st = TEAM3_ENGINEER_SKIN;
		}
		else if ( p.team_no == 2)
		{
			if ( p.skin == PC_SCOUT )
				st = TEAM2_SCOUT_SKIN;
			else if ( p.skin == PC_SNIPER )
				st = TEAM2_SNIPER_SKIN;
			else if ( p.skin == PC_SOLDIER )
				st = TEAM2_SOLDIER_SKIN;
			else if ( p.skin == PC_DEMOMAN )
				st = TEAM2_DEMOMAN_SKIN;
			else if ( p.skin == PC_MEDIC )
				st = TEAM2_MEDIC_SKIN;
			else if ( p.skin == PC_HVYWEAP )
				st = TEAM2_HVYWEAP_SKIN;
			else if ( p.skin == PC_PYRO )
				st = TEAM2_PYRO_SKIN;
			else if ( p.skin == PC_SPY )
				st = TEAM2_SPY_SKIN;
			else if ( p.skin == PC_ENGINEER )
				st = TEAM2_ENGINEER_SKIN;
		}
		else // if ( p.team_no == 1)
		{
			if ( p.skin == PC_SCOUT )
				st = TEAM1_SCOUT_SKIN;
			else if ( p.skin == PC_SNIPER )
				st = TEAM1_SNIPER_SKIN;
			else if ( p.skin == PC_SOLDIER )
				st = TEAM1_SOLDIER_SKIN;
			else if ( p.skin == PC_DEMOMAN )
				st = TEAM1_DEMOMAN_SKIN;
			else if ( p.skin == PC_MEDIC )
				st = TEAM1_MEDIC_SKIN;
			else if ( p.skin == PC_HVYWEAP )
				st = TEAM1_HVYWEAP_SKIN;
			else if ( p.skin == PC_PYRO )
				st = TEAM1_PYRO_SKIN;
			else if ( p.skin == PC_SPY )
				st = TEAM1_SPY_SKIN;
			else if ( p.skin == PC_ENGINEER )
				st = TEAM1_ENGINEER_SKIN;
		}

		if ( p.skin == PC_CIVILIAN )
			st = "base"; // Need a civilian skin
	}
	stuffcmd(p, "skin ");
	stuffcmd(p, st);
	stuffcmd(p, "\n");
	setinfokey(p, "skin", st);
};

//=========================================================================
// Set the details of a player based on his/her class
void() TeamFortress_SetEquipment =
{
	local entity te;
	local entity automan;
	local float kept_items;
	local float tc, tc2;

	if (self.classname != "player")
		return;

    //- OfN Hack to solve monster cleanup when soldier is choosen
    if (self.playerclass == PC_SOLDIER)
    {
        if (!(self.job & JOB_ARMY))
            kill_my_demon();
    }

	kept_items = self.tf_items & (IT_KEY1 | IT_KEY2);
	
	if (self.playerclass != PC_CUSTOM) { //WK -----v
		self.items = 0;
		self.current_weapon = 0;
		self.weapons_carried = 0;

		self.armorclass = 0;

		self.ammo_medikit = 0;
		self.maxammo_medikit = 0;
		self.ammo_detpack = 0;
		self.ammo_c4det = 0;
		self.maxammo_detpack = 0;
		self.items_allowed = 0;
   		self.armor_allowed = 0;
   		self.gravity = 1;
   		self.maxarmor = 0;
		self.weaponmode = 0;
		self.tf_items = 0;
		self.tf_items_flags = 0;
		self.cutf_items = 0;
		self.done_custom = 0;

		//Clear job without losing track of demons, etc.
		self.job = self.job - (self.job & JOB_ALL);
	}
 //WK ------^
		
	self.hover_time = 0;
	if (self.tf_items & NIT_HOVER_BOOTS)
		self.hover_time = MAX_HOVER_FUEL; //10 secs of hovering or so
	self.respawn_time = 0;
	self.heat = 0;
	self.tfstate = self.tfstate - (self.tfstate & TFSTATE_RELOADING);
	if (self.tf_items & NIT_SCUBA) //WK We're a scuba commando!
	{
		self.items = self.items | IT_SUIT;
	 	self.rad_time = 1;
		self.tfstate = self.tfstate | TFSTATE_RADSUIT;
		self.radsuit_finished = time + 666;
	}
	else
	{
		self.tfstate = self.tfstate - (self.tfstate & TFSTATE_RADSUIT);
		self.items = 0;
		self.rad_time = 0;
		self.radsuit_finished = 0;
	}
	self.undercover_skin = 0;
	if (self.undercover_team != 0)
	{
		makeImmune(self,time + 4);
		//self.immune_to_check = time + 4;

		self.undercover_team = 0;
		// Set their color 
		tc = TeamGetColor (self.team_no) - 1;
		tc2 = TeamGetNiceColor (self.team_no);
		SetPlayerColor (self, tc, tc);
	}

	self.is_building = 0;
	self.is_toffingadet = 0;
	self.is_haxxxoring = 0;
	self.is_detpacking = 0;
	self.is_undercover = 0;
	self.is_feigning = 0;
	self.is_unabletospy = 0;
	self.is_malfunctioning = 0;
	self.is_abouttodie = 0; // reset preventing automartyr flag
	
	self.martyr_enemy = self; // reset martyr enemy
	self.stored_deathmsg = 0; // reset stored death message - OfN UNUSED?

	self.impulse = 0;

	if (self.team_no == 0)
		self.lives = -1;

	self.items = self.items | kept_items;

	// Start the Cheat-Checking Cyclic Event if CheatChecking Toggleflag is on
	if (!stof(infokey(NIL,"nospeed")) && (toggleflags&TFLAG_CHEATCHECK))
	{
		te = spawn(); //Cyto
		te.nextthink = time + 2;
		te.think = TeamFortress_CheckForSpeed;
		te.owner = self;
		te.classname = "timer";
	}

	//WK -- Remove flags for job state
	self.job = self.job - (self.job & JOB_ACTIVE);
	self.job = self.job - (self.job & JOB_FULL_HIDE);
	self.job = self.job - (self.job & JOB_TIRED);
	//self.job = self.job - (self.job & JOB_MARTYR_ENEMY);
	self.job_finished = time;

	if ( self.playerclass == PC_CUSTOM ) //WK - Reset the custom class
	{
        self.no_grenades_1 = GetMaxGrens(self,1);
        self.no_grenades_2 = GetMaxGrens(self,2);        

        /*if (self.tp_grenades_1 > 0)
			self.no_grenades_1 = 4;//was 4 //- OfN - returned to 4, it was 5
		if (self.tp_grenades_2 > 0)
			self.no_grenades_2 = 4;// was 4 //- OfN - returned to 4, it was 5

		if (self.tp_grenades_2 == GR_TYPE_NAIL)
			self.no_grenades_2 = 2;// was 1
        if (self.tp_grenades_2 == GR_TYPE_FRAG)
			self.no_grenades_2 = 3;// was 1
        if (self.tp_grenades_2 == GR_TYPE_MIRV)
			self.no_grenades_2 = 2;// was 1
		if (self.tp_grenades_2 == GR_TYPE_FLARE)
			self.no_grenades_2 = 6;

        // Ofn
        if (self.tp_grenades_1 == GR_TYPE_NAIL)
			self.no_grenades_1 = 2;// was 1
        if (self.tp_grenades_1 == GR_TYPE_FRAG)
			self.no_grenades_1 = 3;// was 1
        if (self.tp_grenades_1 == GR_TYPE_MIRV)
			self.no_grenades_1 = 2;// was 1
		if (self.tp_grenades_1 == GR_TYPE_FLARE)
			self.no_grenades_1 = 6;*/

		if (self.tf_items & NIT_AMMO_BANDOLIER)
		{
			self.ammo_rockets = self.maxammo_rockets / 2;
			self.ammo_nails = (3 * self.maxammo_nails) / 4;
			self.ammo_shells = (3 * self.maxammo_shells) / 4;
			self.ammo_cells = (2 * self.maxammo_cells) / 3;
			/*if (self.tp_grenades_1 > 0) //Grant an extra grenade for bandolierians
				self.no_grenades_1 = 5;
			if (self.tp_grenades_2 > 0)
				self.no_grenades_2 = 5;

			if (self.tp_grenades_2 == GR_TYPE_NAIL)
				self.no_grenades_2 = 3;
			if (self.tp_grenades_2 == GR_TYPE_FRAG)
				self.no_grenades_2 = 4;
            if (self.tp_grenades_2 == GR_TYPE_MIRV)
    			self.no_grenades_2 = 3;// was 1
            if (self.tp_grenades_2 == GR_TYPE_FLARE)
			    self.no_grenades_2 = 8;

            if (self.tp_grenades_1 == GR_TYPE_NAIL)
				self.no_grenades_1 = 3;
			if (self.tp_grenades_1 == GR_TYPE_FRAG)
				self.no_grenades_1 = 4;
            if (self.tp_grenades_1 == GR_TYPE_MIRV)
    			self.no_grenades_1 = 3;// was 1
            if (self.tp_grenades_1 == GR_TYPE_FLARE)
			    self.no_grenades_1 = 8;*/
		}
		else
		{
			self.ammo_rockets = self.maxammo_rockets / 4;
			self.ammo_nails = self.maxammo_nails / 2;
			self.ammo_shells = self.maxammo_shells / 2;
			self.ammo_cells = self.maxammo_cells / 2;
		}
		self.ammo_detpack = self.maxammo_detpack;
		self.ammo_c4det = self.maxammo_detpack;
		self.ammo_medikit = self.maxammo_medikit;
		if (self.ammo_medikit > 0 && self.weapons_carried & WEAP_MEDIKIT) {
			te = spawn();
			te.nextthink = time + PC_MEDIC_REGEN_TIME;
			te.think = TeamFortress_Regenerate;
			te.owner = self;
			te.classname = "timer";
		}
		if (self.cutf_items & CUTF_CYBERAUG)
		{
			te = spawn();
			te.nextthink = time + PC_MEDIC_REGEN_TIME;
			te.think = TeamFortress_RegenerateCyber;
			te.owner = self;
			te.classname = "timer";
		}
		// SB only need to activate this with skill
		/*if (self.job & JOB_THIEF)
		{
			te = spawn();
			te.nextthink = time + PC_SPY_CELL_REGEN_TIME;
			te.think = TeamFortress_RegenerateCells;
			te.owner = self;
			te.classname = "timer";
		} */
	
		if (self.cutf_items & CUTF_FULLARMOUR)
			self.armorvalue = self.maxarmor;
		else
			self.armorvalue = self.maxarmor / 2;
	   	self.armortype = self.armor_allowed; //Start with red if red's allowed
		self.armorclass = 0; //Default to no special armor type
		if (self.tf_items & NIT_KEVLAR)
			self.armorclass = self.armorclass | AT_SAVESHOT;
		if (self.tf_items & NIT_GEL)
			self.armorclass = self.armorclass | AT_SAVEMELEE;
		if (self.tf_items & NIT_BLAST)
			self.armorclass = self.armorclass | AT_SAVEEXPLOSION;
		if (self.tf_items & NIT_CERAMIC)
			self.armorclass = self.armorclass | AT_SAVEELECTRICITY;
		if (self.tf_items & NIT_ASBESTOS) //Buying flamer gives this
			self.armorclass = self.armorclass | AT_SAVEFIRE;

		//Support for the "Auto" class itemry
		if (self.tf_items & NIT_AUTOSCANNER || self.weapons_carried & WEAP_MEDIKIT || self.tf_items & NIT_AUTOID) {
				automan = spawn ();
				automan.classname = "timer";
				automan.nextthink = time + 2;
				automan.think = Autoitem_think;
				automan.owner = self;
				automan.enemy = self;
		}

		self.current_weapon = W_BestWeapon ();
	}
	else if ( self.playerclass == PC_SCOUT )
	{
		self.weapons_carried = self.weapons_carried | PC_SCOUT_WEAPONS;
		self.ammo_rockets = PC_SCOUT_INITAMMO_ROCKET;
		self.ammo_nails = PC_SCOUT_INITAMMO_NAIL;
		self.ammo_shells = PC_SCOUT_INITAMMO_SHOT;
		self.ammo_cells = PC_SCOUT_INITAMMO_CELL;
		self.maxammo_rockets = PC_SCOUT_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_SCOUT_MAXAMMO_NAIL;
		self.maxammo_shells = PC_SCOUT_MAXAMMO_SHOT;
		self.maxammo_cells = PC_SCOUT_MAXAMMO_CELL;

		self.no_grenades_1 = PC_SCOUT_GRENADE_INIT_1;
		self.no_grenades_2 = PC_SCOUT_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_SCOUT_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_SCOUT_GRENADE_TYPE_2;
		self.tf_items = PC_SCOUT_TF_ITEMS;
        self.cutf_items = PC_SCOUT_CUTFITEMS;
		self.job = self.job | PC_SCOUT_JOB;

		// the scanner defaults to enemy scanning ON, friendly scanning OFF
		// and movement scanner only OFF
		self.tf_items_flags = self.tf_items_flags | NIT_SCANNER_ENEMY;

		self.armorclass = self.armorclass | PC_SCOUT_INITARMORCLASS;
		self.armortype = PC_SCOUT_INITARMORTYPE;
		self.armorvalue = PC_SCOUT_INITARMOR;
	   	self.armor_allowed = PC_SCOUT_MAXARMORTYPE;
	   	self.maxarmor = PC_SCOUT_MAXARMOR;
		self.current_weapon = WEAP_NAILGUN;

		self.items_allowed = PC_SCOUT_WEAPONS;
		kill_my_demon();

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_NAILGUN;
	}
	else if ( self.playerclass == PC_SNIPER )
	{
		self.weapons_carried = self.weapons_carried | PC_SNIPER_WEAPONS;
		self.ammo_rockets = PC_SNIPER_INITAMMO_ROCKET;
		self.ammo_nails = PC_SNIPER_INITAMMO_NAIL;
		self.ammo_shells = PC_SNIPER_INITAMMO_SHOT;
		self.ammo_cells = PC_SNIPER_INITAMMO_CELL;
		self.maxammo_rockets = PC_SNIPER_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_SNIPER_MAXAMMO_NAIL;
		self.maxammo_shells = PC_SNIPER_MAXAMMO_SHOT;
		self.maxammo_cells = PC_SNIPER_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_SNIPER_GRENADE_INIT_1;
		self.no_grenades_2 = PC_SNIPER_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_SNIPER_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_SNIPER_GRENADE_TYPE_2;
		self.tf_items = PC_SNIPER_TF_ITEMS;
		self.job = self.job | PC_SNIPER_JOB;

		self.armorclass = self.armorclass | PC_SNIPER_INITARMORCLASS;
		self.armortype = PC_SNIPER_INITARMORTYPE;
		self.armorvalue = PC_SNIPER_INITARMOR;
	   	self.armor_allowed = PC_SNIPER_MAXARMORTYPE;
	   	self.maxarmor = PC_SNIPER_MAXARMOR;
		self.current_weapon = WEAP_SNIPER_RIFLE;

		self.items_allowed = PC_SNIPER_WEAPONS;
        self.cutf_items = PC_SNIPER_CUTF_ITEMS; // OFN -OTR

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN;
		kill_my_demon();
	}
	else if ( self.playerclass == PC_SOLDIER )
	{
		self.weapons_carried = self.weapons_carried | PC_SOLDIER_WEAPONS;
		self.ammo_rockets = PC_SOLDIER_INITAMMO_ROCKET;
		self.ammo_nails = PC_SOLDIER_INITAMMO_NAIL;
		self.ammo_shells = PC_SOLDIER_INITAMMO_SHOT;
		self.ammo_cells = PC_SOLDIER_INITAMMO_CELL;
		self.maxammo_rockets = PC_SOLDIER_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_SOLDIER_MAXAMMO_NAIL;
		self.maxammo_shells = PC_SOLDIER_MAXAMMO_SHOT;
		self.maxammo_cells = PC_SOLDIER_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_SOLDIER_GRENADE_INIT_1;
		self.no_grenades_2 = PC_SOLDIER_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_SOLDIER_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_SOLDIER_GRENADE_TYPE_2;
		self.tf_items = PC_SOLDIER_TF_ITEMS;
		self.job = self.job | PC_SOLDIER_JOB;

		self.armorclass = self.armorclass | PC_SOLDIER_INITARMORCLASS;
		self.armortype = PC_SOLDIER_INITARMORTYPE;
		self.armorvalue = PC_SOLDIER_INITARMOR;
	   	self.armor_allowed = PC_SOLDIER_MAXARMORTYPE;
	   	self.maxarmor = PC_SOLDIER_MAXARMOR;
		self.current_weapon = WEAP_ROCKET_LAUNCHER;

		self.items_allowed = PC_SOLDIER_WEAPONS;

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_ROCKET_LAUNCHER;
		//kill_my_demon();
	}
	else if ( self.playerclass == PC_DEMOMAN )
	{
		self.weapons_carried = self.weapons_carried | PC_DEMOMAN_WEAPONS;
		self.ammo_rockets = PC_DEMOMAN_INITAMMO_ROCKET;
		self.ammo_nails = PC_DEMOMAN_INITAMMO_NAIL;
		self.ammo_shells = PC_DEMOMAN_INITAMMO_SHOT;
		self.ammo_cells = PC_DEMOMAN_INITAMMO_CELL;
		self.maxammo_rockets = PC_DEMOMAN_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_DEMOMAN_MAXAMMO_NAIL;
		self.maxammo_shells = PC_DEMOMAN_MAXAMMO_SHOT;
		self.maxammo_cells = PC_DEMOMAN_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_DEMOMAN_GRENADE_INIT_1;
		self.no_grenades_2 = PC_DEMOMAN_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_DEMOMAN_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_DEMOMAN_GRENADE_TYPE_2;
		self.tf_items = PC_DEMOMAN_TF_ITEMS;
		self.job = self.job | PC_DEMOMAN_JOB;
		self.cutf_items = PC_DEMOMAN_CUTFITEMS;

		// Detpacks
		self.ammo_detpack = PC_DEMOMAN_INITAMMO_DETPACK;
		self.maxammo_detpack = PC_DEMOMAN_MAXAMMO_DETPACK;

		self.armorclass = self.armorclass | PC_DEMOMAN_INITARMORCLASS;
		self.armortype = PC_DEMOMAN_INITARMORTYPE;
		self.armorvalue = PC_DEMOMAN_INITARMOR;
	   	self.armor_allowed = PC_DEMOMAN_MAXARMORTYPE;
	   	self.maxarmor = PC_DEMOMAN_MAXARMOR;
		self.current_weapon = WEAP_GRENADE_LAUNCHER;
		kill_my_demon();

        self.ammo_c4det = 1; // - OfN

		self.items_allowed = PC_DEMOMAN_WEAPONS;

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_GRENADE_LAUNCHER;
	}
	else if ( self.playerclass == PC_MEDIC )
	{
		self.weapons_carried = self.weapons_carried | PC_MEDIC_WEAPONS;
		self.ammo_rockets = PC_MEDIC_INITAMMO_ROCKET;
		self.ammo_nails = PC_MEDIC_INITAMMO_NAIL;
		self.ammo_shells = PC_MEDIC_INITAMMO_SHOT;
		self.ammo_cells = PC_MEDIC_INITAMMO_CELL;
		self.maxammo_rockets = PC_MEDIC_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_MEDIC_MAXAMMO_NAIL;
		self.maxammo_shells = PC_MEDIC_MAXAMMO_SHOT;
		self.maxammo_cells = PC_MEDIC_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_MEDIC_GRENADE_INIT_1;
		self.no_grenades_2 = PC_MEDIC_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_MEDIC_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_MEDIC_GRENADE_TYPE_2;
		self.tf_items = PC_MEDIC_TF_ITEMS;
		self.job = self.job | PC_MEDIC_JOB;

		self.armorclass = self.armorclass | PC_MEDIC_INITARMORCLASS;
		self.armortype = PC_MEDIC_INITARMORTYPE;
		self.armorvalue = PC_MEDIC_INITARMOR;
	   	self.armor_allowed = PC_MEDIC_MAXARMORTYPE;
	   	self.maxarmor = PC_MEDIC_MAXARMOR;
		self.current_weapon = WEAP_LIGHT_ASSAULT;

		self.ammo_medikit = PC_MEDIC_INITAMMO_MEDIKIT;
		self.maxammo_medikit = PC_MEDIC_MAXAMMO_MEDIKIT;

		// Start the Regeneration Cyclic Event
		te = spawn();
		te.nextthink = time + PC_MEDIC_REGEN_TIME;
		te.think = TeamFortress_Regenerate;
		te.owner = self;
		te.classname = "timer";

		self.items_allowed = PC_MEDIC_WEAPONS;

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_LIGHT_ASSAULT;
		kill_my_demon();
	}
	else if ( self.playerclass == PC_HVYWEAP )
	{
		self.weapons_carried = self.weapons_carried | PC_HVYWEAP_WEAPONS;
		self.ammo_rockets = PC_HVYWEAP_INITAMMO_ROCKET;
		self.ammo_nails = PC_HVYWEAP_INITAMMO_NAIL;
		self.ammo_shells = PC_HVYWEAP_INITAMMO_SHOT;
		self.ammo_cells = PC_HVYWEAP_INITAMMO_CELL;
		self.maxammo_rockets = PC_HVYWEAP_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_HVYWEAP_MAXAMMO_NAIL;
		self.maxammo_shells = PC_HVYWEAP_MAXAMMO_SHOT;
		self.maxammo_cells = PC_HVYWEAP_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_HVYWEAP_GRENADE_INIT_1;
		self.no_grenades_2 = PC_HVYWEAP_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_HVYWEAP_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_HVYWEAP_GRENADE_TYPE_2;
		self.tf_items = PC_HVYWEAP_TF_ITEMS;
		self.job = self.job | PC_HVYWEAP_JOB;

		self.armorclass = self.armorclass | PC_HVYWEAP_INITARMORCLASS;
		self.armortype = PC_HVYWEAP_INITARMORTYPE;
		self.armorvalue = PC_HVYWEAP_INITARMOR;
	   	self.armor_allowed = PC_HVYWEAP_MAXARMORTYPE;
	   	self.maxarmor = PC_HVYWEAP_MAXARMOR;
		self.current_weapon = WEAP_SUPER_SHOTGUN;
		self.cutf_items = CUTF_HWGUY;

		self.items_allowed = PC_HVYWEAP_WEAPONS;

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_ROCKET_LAUNCHER;
		kill_my_demon();
	}
	else if ( self.playerclass == PC_PYRO )
	{
		self.weapons_carried = self.weapons_carried | PC_PYRO_WEAPONS;
		self.ammo_rockets = PC_PYRO_INITAMMO_ROCKET;
		self.ammo_nails = PC_PYRO_INITAMMO_NAIL;
		self.ammo_shells = PC_PYRO_INITAMMO_SHOT;
		self.ammo_cells = PC_PYRO_INITAMMO_CELL;
		self.maxammo_rockets = PC_PYRO_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_PYRO_MAXAMMO_NAIL;
		self.maxammo_shells = PC_PYRO_MAXAMMO_SHOT;
		self.maxammo_cells = PC_PYRO_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_PYRO_GRENADE_INIT_1;
		self.no_grenades_2 = PC_PYRO_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_PYRO_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_PYRO_GRENADE_TYPE_2;
		self.tf_items = PC_PYRO_TF_ITEMS;
		self.job = self.job | PC_PYRO_JOB;

		self.armorclass = self.armorclass | PC_PYRO_INITARMORCLASS;
		self.armortype = PC_PYRO_INITARMORTYPE;
		self.armorvalue = PC_PYRO_INITARMOR;
	   	self.armor_allowed = PC_PYRO_MAXARMORTYPE;
	   	self.maxarmor = PC_PYRO_MAXARMOR;
		self.current_weapon = WEAP_FLAMETHROWER;
		self.items_allowed = PC_PYRO_WEAPONS;
		kill_my_demon();

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER;
	}
	else if ( self.playerclass == PC_CIVILIAN )
	{
		self.weapons_carried = self.weapons_carried | PC_CIVILIAN_WEAPONS;
		self.ammo_rockets = PC_CIVILIAN_INITAMMO_ROCKET;
		self.ammo_nails = PC_CIVILIAN_INITAMMO_NAIL;
		self.ammo_shells = PC_CIVILIAN_INITAMMO_SHOT;
		self.ammo_cells = PC_CIVILIAN_INITAMMO_CELL;
		self.maxammo_rockets = PC_CIVILIAN_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_CIVILIAN_MAXAMMO_NAIL;
		self.maxammo_shells = PC_CIVILIAN_MAXAMMO_SHOT;
		self.maxammo_cells = PC_CIVILIAN_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_CIVILIAN_GRENADE_INIT_1;
		self.no_grenades_2 = PC_CIVILIAN_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_CIVILIAN_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_CIVILIAN_GRENADE_TYPE_2;
		self.tf_items = PC_CIVILIAN_TF_ITEMS;
		self.job = self.job | PC_CIVILIAN_JOB;

		self.armorclass = self.armorclass | PC_CIVILIAN_INITARMORCLASS;
		self.armortype = PC_CIVILIAN_INITARMORTYPE;
		self.armorvalue = PC_CIVILIAN_INITARMOR;
	   	self.armor_allowed = PC_CIVILIAN_MAXARMORTYPE;
	   	self.maxarmor = PC_CIVILIAN_MAXARMOR;
		self.current_weapon = WEAP_AXE;
		self.items_allowed = PC_CIVILIAN_WEAPONS;
		self.cutf_items = PC_CIVILIAN_CUTFITEMS;

		// set the weapon icons on the status bar
		self.items = 0;
		kill_my_demon();
	}
	else if ( self.playerclass == PC_SPY )
	{
		self.weapons_carried = self.weapons_carried | PC_SPY_WEAPONS;
		self.ammo_rockets = PC_SPY_INITAMMO_ROCKET;
		self.ammo_nails = PC_SPY_INITAMMO_NAIL;
		self.ammo_shells = PC_SPY_INITAMMO_SHOT;
		self.ammo_cells = PC_SPY_INITAMMO_CELL;
		self.maxammo_rockets = PC_SPY_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_SPY_MAXAMMO_NAIL;
		self.maxammo_shells = PC_SPY_MAXAMMO_SHOT;
		self.maxammo_cells = PC_SPY_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_SPY_GRENADE_INIT_1;
		self.no_grenades_2 = PC_SPY_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_SPY_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_SPY_GRENADE_TYPE_2;
		self.tf_items = PC_SPY_TF_ITEMS;
		self.job = self.job | PC_SPY_JOB;

		self.armorclass = self.armorclass | PC_SPY_INITARMORCLASS;
		self.armortype = PC_SPY_INITARMORTYPE;
		self.armorvalue = PC_SPY_INITARMOR;
	   	self.armor_allowed = PC_SPY_MAXARMORTYPE;
	   	self.maxarmor = PC_SPY_MAXARMOR;
		self.current_weapon = WEAP_TRANQ;
		self.items_allowed = PC_SPY_WEAPONS;
		self.cutf_items = PC_SPY_CUTFITEMS;

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN;
		

		// If the Spy only has invis, start the Spy's cell regen timer
		if (invis_only == TRUE)
		{
			te = spawn();
			te.nextthink = time + PC_SPY_CELL_REGEN_TIME;
			te.think = TeamFortress_RegenerateCells;
			te.owner = self;
			te.classname = "timer";
		}
	}
	else if ( self.playerclass == PC_ENGINEER )
	{
		self.weapons_carried = self.weapons_carried | PC_ENGINEER_WEAPONS;
		self.ammo_rockets = PC_ENGINEER_INITAMMO_ROCKET;
		self.ammo_nails = PC_ENGINEER_INITAMMO_NAIL;
		self.ammo_shells = PC_ENGINEER_INITAMMO_SHOT;
		self.ammo_cells = PC_ENGINEER_INITAMMO_CELL;
		self.maxammo_rockets = PC_ENGINEER_MAXAMMO_ROCKET;
		self.maxammo_nails = PC_ENGINEER_MAXAMMO_NAIL;
		self.maxammo_shells = PC_ENGINEER_MAXAMMO_SHOT;
		self.maxammo_cells = PC_ENGINEER_MAXAMMO_CELL;
	
		self.no_grenades_1 = PC_ENGINEER_GRENADE_INIT_1;
		self.no_grenades_2 = PC_ENGINEER_GRENADE_INIT_2;
		self.tp_grenades_1 = PC_ENGINEER_GRENADE_TYPE_1;
		self.tp_grenades_2 = PC_ENGINEER_GRENADE_TYPE_2;
		self.tf_items = PC_ENGINEER_TF_ITEMS;
		self.job = self.job | PC_ENGINEER_JOB;

		self.armorclass = self.armorclass | PC_ENGINEER_INITARMORCLASS;
		self.armortype = PC_ENGINEER_INITARMORTYPE;
		self.armorvalue = PC_ENGINEER_INITARMOR;
	   	self.armor_allowed = PC_ENGINEER_MAXARMORTYPE;
	   	self.maxarmor = PC_ENGINEER_MAXARMOR;
		self.current_weapon = WEAP_LASER;
		self.items_allowed = PC_ENGINEER_WEAPONS;
		self.cutf_items = PC_ENGINEER_CUTFITEMS;

		// set the weapon icons on the status bar
		self.items = self.items | IT_SHOTGUN | IT_SUPER_SHOTGUN;
		kill_my_demon();
	}
	else if ( self.playerclass == PC_UNDEFINED )
	{
		self.items = 0;
		self.ammo_rockets = 0;
		self.ammo_nails = 0;
		self.ammo_shells = 0;
		self.ammo_cells = 0;

		self.no_grenades_1 = 0;
		self.no_grenades_2 = 0;
		self.tp_grenades_1 = 0;
		self.tp_grenades_2 = 0;
	
		self.armorclass = 0;
		self.armortype = 0;
		self.armorvalue = 0;
		self.weapon = 0;
		self.current_weapon = 0;
		self.weapons_carried = 0;

		self.flags = FL_CLIENT | FL_NOTARGET; // | FL_ONGROUND;
		self.waterlevel = 3;
		self.takedamage = DAMAGE_NO;
		self.solid = SOLID_NOT;
		self.movetype = MOVETYPE_NOCLIP;

		self.model = "";
		self.mdl = "";
		self.modelindex = 0;
		self.weaponmodel = "";
		modelindex_player = 0;
		self.tfstate = self.tfstate | TFSTATE_RELOADING;
	
		setmodel(self, "");
	}
    
    
    if (stock_mode==1) //- OfN - Stock classes don't get a job when stock_mode is 1
        self.job=0;

    //- OfN - Set initial grens number
    self.no_grenades_1 = GetMaxGrens(self,1);
    self.no_grenades_2 = GetMaxGrens(self,2);   
    
    //- OfN - Set army timer //
    if (self.job & JOB_ARMY)
    {
        SetArmyTimer();
    }	

    if (no_otr) // if its disabled get it off
        self.cutf_items = self.cutf_items - (self.cutf_items & CUTF_OTR);
    if (no_chaplan)
        self.job = self.job - (self.job & JOB_CHAPLAN);

	// Give normal classes the hook
	// Custom classes get it in 'drop into custom class gen'
	if (allow_hook && self.playerclass != PC_UNDEFINED && self.playerclass != PC_CUSTOM)
		self.weapons_carried = self.weapons_carried | WEAP_HOOK;

	W_SetCurrentAmmo ();
};

//=========================================================================
// Return the max amount of ammo the Retriever can carry, based on his class
float(entity Retriever, float AmmoType) TeamFortress_GetMaxAmmo =
{
	if (AmmoType == IT_SHELLS)
		return Retriever.maxammo_shells;
	else if (AmmoType == IT_NAILS)
		return Retriever.maxammo_nails;
	else if (AmmoType == IT_CELLS)
		return Retriever.maxammo_cells;
	else if (AmmoType == IT_ROCKETS)
		return Retriever.maxammo_rockets;
	else if (AmmoType == WEAP_MEDIKIT)
		return Retriever.maxammo_medikit;
	else if (AmmoType == 131072) //WK Used to be WEAP_DETPACK
		return Retriever.maxammo_detpack;

	RPrint("Error in TeamFortress_GetMaxAmmo()\n");
	RPrint("Invalid ammo type passed.\n");
	return 0;
};

//=========================================================================
// Return 1 if the Retriever is allowed to pick up the Weapon
float(entity Retriever, float WeaponType) TeamFortress_CanGetWeapon =
{
	if ( Retriever.items_allowed & WeaponType )
		return TRUE;

	return FALSE;
};


//=========================================================================
// Print a string to Player, describing this type of armor
//CH returns number effected
float(entity Player, float Armorclass) TeamFortress_DescribeArmor =
{
	local float num;
	num = 0;
	if (Armorclass == 0)
		return num;

	if (Armorclass & AT_SAVEFIRE) {
		sprint (Player, PRINT_HIGH, "Asbestos ");
		num = num + 1;
	}
	if (Armorclass & AT_SAVEEXPLOSION) {
		sprint (Player, PRINT_HIGH, "Blast ");
		num = num + 1;
	}
	if (Armorclass & AT_SAVEELECTRICITY) {
		sprint (Player, PRINT_HIGH, "Ceramic ");
		num = num + 1;
	}
	if (Armorclass & AT_SAVEMELEE) {
		sprint (Player, PRINT_HIGH, "Gel ");
		num = num + 1;
	}
	if (Armorclass & AT_SAVESHOT) {
		sprint (Player, PRINT_HIGH, "Kevlar ");
		num = num + 1;
	}

	sprint (Player, PRINT_HIGH, "armor");
	return num;
};

//=========================================================================
// Controls the equipment a class receives from backpacks
float(entity Retriever, entity Items) TeamFortress_AddBackpackItems =
{
	// If you want the classes to _not_ start off with all their legal
	// weapons, then you may want them to be able to pick up weapons
	// from backpacks. If so, this is where to do it.
	// For now, return. 
	return 0;
};

//=========================================================================
// Return a string containing the class name for pc
string(float pc) TeamFortress_GetClassName =
{
	if ( pc == PC_SCOUT )
		return "Scout";
	else if ( pc == PC_SNIPER )
		return "Sniper";
	else if ( pc == PC_SOLDIER )
		return "Soldier";
	else if ( pc == PC_DEMOMAN )
		return "Demolitions Man";
	else if ( pc == PC_MEDIC )
		return "Combat Medic";
	else if ( pc == PC_HVYWEAP )
		return "Heavy Weapons Guy";
	else if ( pc == PC_PYRO )
		return "Pyro";
	else if ( pc == PC_SPY )
		return "Spy";
	else if ( pc == PC_ENGINEER )
		return "Engineer";
	else if ( pc == PC_CIVILIAN )
		return "Civilian";
	else if ( pc == PC_UNDEFINED )
		return "Observer";
	else if ( pc == PC_RANDOM)
		return "Random Playerclass";
	else if ( pc == PC_CUSTOM)
		return "Custom Playerclass";
};

//=========================================================================
// Return a string containing the class name for pc
string(float pc) TeamFortress_GetJobName =
{
	if ( pc & JOB_THIEF )
		return "Thief";
	else if ( pc & JOB_RUNNER )
		return "Runner";
	else if ( pc & JOB_WARLOCK )
		return "Warlock";
	else if ( pc & JOB_CHAPLAN )
		return "Combat Chaplan";
	else if ( pc & JOB_BERSERKER )
		return "Nordish Berserker";
	else if ( pc & JOB_GUERILLA )
		return "Communist Rebel";
	else if ( pc & JOB_JUDOKA )
		return "Judo Black Belt";
	else if ( pc & JOB_ARMY )
		return "Army Member";
	else if ( pc & JOB_HACKER )
		return "Hacker";
	else if ( pc & JOB_MARTYR )
		return "Martyr";
  	else if ( pc & JOB_CRUSADER )
		return "Crusader";
	else
		return "Custom Playerclass";
};

//=========================================================================
// Display the class of Player to Viewer
void(entity Viewer, float pc, float rpc) TeamFortress_PrintClassName =
{
	local string st;
	st = TeamFortress_GetClassName(pc);
	sprint (Viewer, PRINT_HIGH, st);

	if (rpc != 0)
		sprint (Viewer, PRINT_HIGH, " (Random)");
	sprint (Viewer, PRINT_HIGH, "\n");
};

//=========================================================================
// Display the job of a custom class to Viewer
void(entity Viewer, float pc) TeamFortress_PrintJobName =
{
	local string st;
	st = TeamFortress_GetJobName(pc);
	sprint (Viewer, PRINT_HIGH, st);
	sprint (Viewer, PRINT_HIGH, "\n");
};

//=========================================================================
// Say the class of Player to him/her
#ifdef SPEECH
void(entity player) TeamFortress_SayClassName =
{
	if ( player.playerclass == PC_SCOUT )
		stuffcmd(player, "play speech/scout.wav\n");
	else if ( player.playerclass == PC_SNIPER )
		stuffcmd(player, "play speech/sniper.wav\n");
	else if ( player.playerclass == PC_SOLDIER )
		stuffcmd(player, "play speech/soldier.wav\n");
	else if ( player.playerclass == PC_DEMOMAN )
		stuffcmd(player, "play speech/demoman.wav\n");
	else if ( player.playerclass == PC_MEDIC )
		stuffcmd(player, "play speech/medic.wav\n");
	else if ( player.playerclass == PC_HVYWEAP )
		stuffcmd(player, "play speech/hvyweap.wav\n");
	else if ( player.playerclass == PC_PYRO )
		stuffcmd(player, "play speech/pyro.wav\n");
	else if ( player.playerclass == PC_SPY )
		stuffcmd(player, "play speech/spy.wav\n");
	else if ( player.playerclass == PC_ENGINEER )
		stuffcmd(player, "play speech/engineer.wav\n");
	else if ( player.playerclass == PC_CIVILIAN )
		stuffcmd(player, "play speech/civilian.wav\n");
};
#endif

//=========================================================================
// Remove all the timers for this player
// This function is _always_ called when a player dies.
void() TeamFortress_RemoveTimers =
{
	local entity te;
	local entity oself;

	self.leg_damage = 0;
	self.is_undercover = 0;
	self.is_building = 0;
	self.building = NIL;

	//CH
	stuffcmd (self, "throwgren\n"); //Throw any grenades
	stuffcmd (self, "impulse 169\n"); //Stop laying dets

	// Clear the sniper's aiming
	if (self.tfstate & TFSTATE_AIMING)
	{
		self.tfstate = self.tfstate - TFSTATE_AIMING;
		TeamFortress_SetSpeed(self);
		self.heat = 0;
	}

	// Remove all the timer entities for this player
	te = find(NIL, classname, "timer");
	while (te)
	{
		//WK Judokatimer is a little weird
		if (te.netname == "judokatimer" && te.think == JudokaRearm)
		{
			if (te.owner == self || te.enemy == self)
			{
				oself = self;
				self = te;
				self.think();
				self = oself;
				te.think = SUB_Remove;
				te.nextthink = time + 0.1;
			}
			te = find(te, classname, "timer");
		}
		else if (te.owner == self)
		{
			//WK Fix our new little flash timer
			if (te.netname == "flashtimer")
			{
				self.FlashTime = 0;
				stuffcmd(self, "v_cshift 0\n");
				stuffcmd(self, "r_norefresh 0;wait;echo;wait;echo;wait;echo;wait;echo\n");
				dremove(te);
				te = find(NIL, classname, "timer");
			}
			//WK Support for the curse timer
			else if (te.netname == "bastardtimer")
			{
				if (self.has_disconnected == TRUE)
				{
					dremove(te);
					te = find(NIL, classname, "timer");
				}
				else 
					te = find(te, classname, "timer");
			}
			else
			{
				dremove(te);
				te = find(NIL, classname, "timer");
			}
		}
		else
			te = find(te, classname, "timer");
	}

	// Drop any GoalItems
	te = find (NIL, classname, "item_tfgoal");
	while (te)
	{
		if (te.owner == self)
		{
			// Remove it from the player, if it is supposed to be
			if (!(te.goal_activation & TFGI_KEEP))
			{
				tfgoalitem_RemoveFromPlayer(te, self, 0);
			}

			// CTF support
			if (CTF_Map == TRUE && te.goal_no == CTF_FLAG1)
			{
				bprint(PRINT_HIGH, self.netname);
      			bprint(PRINT_HIGH, " ���� the ���� flag!\n");
			}
			else if (CTF_Map == TRUE && te.goal_no == CTF_FLAG2)
			{
				bprint(PRINT_HIGH, self.netname);
                bprint(PRINT_HIGH, " ���� the ��� flag!\n");
			}

		}
		te = find(te, classname, "item_tfgoal");
	}

	// Reset detpacks being disarmed to not being disarmed
	te = find (NIL, classname, "detpack");
	while (te)
	{
		if ((te.weaponmode == 1) && (te.enemy == self))
		{
			te.weaponmode = 0;
		}
		te = find(te, classname, "detpack");
	}

	// detonate all of the players pipebombs
	TeamFortress_DetonatePipebombs();

    // OfN Remove holo if player dies! 
    if (self.has_holo > 0) RemoveHolo(self);

	stuffcmd(self, "v_idlescale 0\n");
	stuffcmd(self, "v_cshift 0 0 0 0\n");
	self.item_list = 0;
	self.FlashTime = 0;

	// Remove Menu
	CenterPrint(self, "\n");
	self.menu_count = MENU_REFRESH_RATE;
	self.current_menu = MENU_DEFAULT;
	self.impulse = 0;
};

//=========================================================================
// Setup the Respawn delays for this player
void(float Suicided) TeamFortress_SetupRespawn =
{
	local float restime;
	local string db;

	if (self.respawn_time > time)
		return;		// already respawning

	// Setup Respawn Delay
	if (toggleflags & TFLAG_RESPAWNDELAY)
		restime = respawn_delay_time;
	else 
		restime = 0;

	// Suiciders can't respawn immediately
	if (Suicided)
		restime = restime + 5;

	// Remove a life
	if (self.lives > 0 && prematch < time)
	{
		self.lives = self.lives - 1;
/*		if (self.team_no == 1) team1total = team1total - 1;
		else if (self.team_no == 2) team1total = team2total - 1;
		else if (self.team_no == 3) team1total = team3total - 1;
		else if (self.team_no == 4) team1total = team4total - 1;*///- ???
		
		
	}

	if (self.lives != -1)
	{
		if (self.lives == 0)
		{
			// Move to Observer mode when you die
			PlayerObserverMode();
			//if (livesperguy > 1)
			//{
				sprint (self, PRINT_HIGH, "NO lives left, returning to Observer mode.\n");
				bprint (PRINT_MEDIUM, self.netname);
				bprint (PRINT_MEDIUM, " ran out of lives!\n");
			//}
			return;
		}

		if (self.lives == 1)
			sprint (self, PRINT_HIGH, "LAST life.\n");
		else
		{
			db = ftos(self.lives);
			sprint(self, PRINT_HIGH, db);
			sprint (self, PRINT_HIGH, " lives left.\n");
		}
	}//*/// ???

	// Do this after life calculation, so people without any
	// lives left can respawn back to Observer mode without a delay.
	self.respawn_time = time + restime;

	if (restime > 3)
	{
		db = ftos(restime);

		sprint(self, PRINT_HIGH, db);
		sprint(self, PRINT_HIGH, " seconds till respawn.\n");
	}
};

//=========================================================================
// Check all stats to make sure they're good for this class
void() TeamFortress_CheckClassStats =
{
	// Check armor
	if (self.armortype > self.armor_allowed)
		self.armortype = self.armor_allowed;
	if (self.armorvalue > self.maxarmor)
		self.armorvalue = self.maxarmor;
	if (self.armortype < 0)
		self.armortype = 0;
	if (self.armorvalue < 0)
		self.armorvalue = 0;
	// Check ammo
	if (self.ammo_shells > TeamFortress_GetMaxAmmo(self,IT_SHELLS))
		self.ammo_shells = TeamFortress_GetMaxAmmo(self,IT_SHELLS);
	if (self.ammo_shells < 0)
		self.ammo_shells = 0;
	if (self.ammo_nails > TeamFortress_GetMaxAmmo(self,IT_NAILS))
		self.ammo_nails = TeamFortress_GetMaxAmmo(self,IT_NAILS);
	if (self.ammo_nails < 0)
		self.ammo_nails = 0;
	if (self.ammo_rockets > TeamFortress_GetMaxAmmo(self,IT_ROCKETS))
		self.ammo_rockets = TeamFortress_GetMaxAmmo(self,IT_ROCKETS);		
	if (self.ammo_rockets < 0)
		self.ammo_rockets = 0;
	if (self.ammo_cells > TeamFortress_GetMaxAmmo(self,IT_CELLS))
		self.ammo_cells = TeamFortress_GetMaxAmmo(self,IT_CELLS);		
	if (self.ammo_cells < 0)
		self.ammo_cells = 0;
	if (self.ammo_medikit > TeamFortress_GetMaxAmmo(self,WEAP_MEDIKIT))
		self.ammo_medikit = TeamFortress_GetMaxAmmo(self,WEAP_MEDIKIT);		
	if (self.ammo_medikit < 0)
		self.ammo_medikit = 0;
	if (self.ammo_detpack > TeamFortress_GetMaxAmmo(self,131072))
		self.ammo_detpack = TeamFortress_GetMaxAmmo(self,131072);		
	if (self.ammo_detpack < 0)
		self.ammo_detpack = 0;
	// Check Grenades
	if (self.no_grenades_1 < 0)
		self.no_grenades_1 = 0;
	if (self.no_grenades_2 < 0)
		self.no_grenades_2 = 0;
	// Check health
	if (self.health > self.max_health && !(self.items & IT_SUPERHEALTH))
		TF_T_Damage (self, NIL, NIL, (self.max_health - self.health), 0, TF_TD_NOSOUND);
	if (self.health < 0)
		T_Heal(self, (self.health - self.health), 0);

	// Update armor picture
	self.items = self.items & ~(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3);
	if (self.armortype >= 0.8)
		self.items = self.items | IT_ARMOR3;
	else if (self.armortype >= 0.6)
		self.items = self.items | IT_ARMOR2;
	else if (self.armortype >= 0.3)
		self.items = self.items | IT_ARMOR1;
};

//=========================================================================
// AMMOBOX Handling
//=========================================================================
// Throw an ammo box with 10 shells, 10 nails, 5 cells or 5 rockets
void (float type) TeamFortress_DropAmmo =
{
	local float ammo = 0;

    if (type == 1)
	{
		ammo = DROP_SHELLS;
		if (self.ammo_shells < ammo)
		{
/*CH who cares, we need space
			// ENGINEER can make ammo
			if (self.playerclass == PC_ENGINEER)
			{
				if ((self.ammo_cells / AMMO_COST_SHELLS) > (ammo - self.ammo_shells))
				{
					sprint (self, PRINT_HIGH, "you make some shells.\n");
					self.ammo_cells = self.ammo_cells - ((ammo - self.ammo_shells) * AMMO_COST_SHELLS);
					self.ammo_shells = ammo;
				}
			}

			if (self.ammo_shells < ammo)
*/				return;
		}

		self.ammo_shells = self.ammo_shells - ammo;
	}
	else if (type == 2)
	{
		ammo = DROP_NAILS;
		if (self.ammo_nails < ammo)
		{
/*CH who cares, we need space
			// ENGINEER can make ammo
			if (self.playerclass == PC_ENGINEER)
			{
				if ((self.ammo_cells / AMMO_COST_NAILS) > (ammo - self.ammo_nails))
				{
					sprint (self, PRINT_HIGH, "you make some nails.\n");
					self.ammo_cells = self.ammo_cells - ((ammo - self.ammo_nails) * AMMO_COST_NAILS);
					self.ammo_nails = ammo;
				}
			}

			if (self.ammo_nails < ammo)
*/				return;
		}

		self.ammo_nails = self.ammo_nails - ammo;
	}
	else if (type == 3)
	{
		ammo = DROP_ROCKETS;
		if (self.ammo_rockets < ammo)
		{
/*CH who cares, we need space
			// ENGINEER can make ammo
			if (self.playerclass == PC_ENGINEER)
			{
				if ((self.ammo_cells / AMMO_COST_ROCKETS) > (ammo - self.ammo_rockets))
				{
					sprint (self, PRINT_HIGH, "you make some rockets.\n");
					self.ammo_cells = self.ammo_cells - ((ammo - self.ammo_rockets) * AMMO_COST_ROCKETS);
					self.ammo_rockets = ammo;
				}
			}

			if (self.ammo_rockets < ammo)
*/				return;
		}

		self.ammo_rockets = self.ammo_rockets - ammo;
	}
	else if (type == 4)
	{
		ammo = DROP_CELLS;
		if (self.ammo_cells < ammo)
		{
/*CH who cares, we need space
			// ENGINEER can make ammo
			if (self.playerclass == PC_ENGINEER)
			{
				if ((self.ammo_cells / AMMO_COST_CELLS) > (ammo - self.ammo_cells))
				{
					sprint (self, PRINT_HIGH, "you make some cells.\n");
					self.ammo_cells = self.ammo_cells - ((ammo - self.ammo_cells) * AMMO_COST_CELLS);
					self.ammo_cells = ammo;
				}
			}

			if (self.ammo_cells < ammo)
*/				return;
		}

		self.ammo_cells = self.ammo_cells - ammo;
	}
	W_SetCurrentAmmo();

	if (self.team_no != 0)
	{
		increment_team_ammoboxes(self.team_no);
		if (num_team_ammoboxes(self.team_no) > (MAX_WORLD_AMMOBOXES / number_of_teams))
			RemoveOldAmmobox(self.team_no);
	}
	else 
	{
		num_world_ammoboxes = num_world_ammoboxes + 1;
		if (num_world_ammoboxes > MAX_WORLD_AMMOBOXES)
			RemoveOldAmmobox(0);
	}

	newmis = spawn();
	newmis.aflag = ammo;
	newmis.weapon = type;
	if (newmis.weapon == 1)
		newmis.ammo_shells = ammo;
	else if (newmis.weapon == 2)
		newmis.ammo_nails = ammo;
	else if (newmis.weapon == 3)
		newmis.ammo_rockets = ammo;
	else if (newmis.weapon == 4)
		newmis.ammo_cells = ammo;
	newmis.enemy = self;
	newmis.health = time;
	newmis.movetype = MOVETYPE_TOSS;
	newmis.solid = SOLID_TRIGGER;
	newmis.classname = "ammobox";
	newmis.team_no = self.team_no;

	makevectors (self.v_angle);

	if (self.v_angle_x)
		newmis.velocity = v_forward*400 + v_up * 200;
	else
	{
		newmis.velocity = aim(self, 10000);
		newmis.velocity = newmis.velocity * 400;
		newmis.velocity_z = 200;
	}

	newmis.avelocity = '0 300 0';
	setsize (newmis, '0 0 0', '0 0 0');		
	setorigin (newmis, self.origin);
	newmis.nextthink = time + 30;	// remove after 30 seconds
	newmis.think = SUB_Remove;
	newmis.touch = TeamFortress_AmmoboxTouch;
	newmis.skin = type - 1;
	setmodel (newmis, "progs/ammobox.mdl");
};

void () TeamFortress_AmmoboxTouch =
{
	local float took;
	local string quantity;

	took = 0;

	// Cant touch own ammobox for 2 seconds after throwing
	if ((other == self.enemy) && (time < self.health + 2))
		return;			

	if (other.health <= 0)
		return;

    
    // Return if other is not a player
	if (other.classname != "player") //- OfN - Now grunt can take em
	{
        if (other.classname != "monster_army") return;

    	num_world_ammoboxes = num_world_ammoboxes - 1;
	    decrement_team_ammoboxes(self.team_no);

        other.ammo_shells = other.ammo_shells + self.ammo_shells;
        other.ammo_nails = other.ammo_nails + self.ammo_nails;
    	other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
		other.ammo_cells = other.ammo_cells + self.ammo_cells;

        grunty_boundammo(other);

        PrintFromSoldier(other,other.real_owner,"i picked up some ammo.\n");

        sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);

        dremove(self);
       	self = other;

        return;
    }

	num_world_ammoboxes = num_world_ammoboxes - 1;
	decrement_team_ammoboxes(self.team_no);

	// discard backpack
	if (self.weapon == 0)
	{
		sprint(other, PRINT_LOW, "You got ");
		if (self.ammo_shells > 0)
		{
			other.ammo_shells = other.ammo_shells + self.ammo_shells;
			quantity = ftos(self.ammo_shells);
			sprint(other, PRINT_LOW, quantity, " shells  ");
		}	
		if (self.ammo_nails > 0)
		{
			other.ammo_nails = other.ammo_nails + self.ammo_nails;
			quantity = ftos(self.ammo_nails);
			sprint(other, PRINT_LOW, quantity, " nails  ");
		}	
		if (self.ammo_rockets > 0)
		{
			other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
			quantity = ftos(self.ammo_rockets);
			sprint(other, PRINT_LOW, quantity, " rockets  ");
		}	
		if (self.ammo_cells > 0)
		{
			other.ammo_cells = other.ammo_cells + self.ammo_cells;
			quantity = ftos(self.ammo_cells);
			sprint(other, PRINT_LOW, quantity, " cells  ");
		}	
		sprint(other, PRINT_LOW, "\n");
	}
	// shotgun
	else if (self.weapon == 1)
	{
		if (other.ammo_shells >= TeamFortress_GetMaxAmmo(other,IT_SHELLS))
			return;
		other.ammo_shells = other.ammo_shells + self.aflag;
		self.netname = "shells";
	}
	// spikes
	else if (self.weapon == 2)
	{
		if (other.ammo_nails >= TeamFortress_GetMaxAmmo(other,IT_NAILS))
			return;
		other.ammo_nails = other.ammo_nails + self.aflag;
		self.netname = "nails";
	}
	//	rockets
	else if (self.weapon == 3)
	{
		if (other.ammo_rockets >= TeamFortress_GetMaxAmmo(other,IT_ROCKETS))
			return;
		other.ammo_rockets = other.ammo_rockets + self.aflag;
		self.netname = "rockets";
	}
	//	cells
	else if (self.weapon == 4)
	{
		if (other.ammo_cells >= TeamFortress_GetMaxAmmo(other,IT_CELLS))
			return;
		other.ammo_cells = other.ammo_cells + self.aflag;
		self.netname = "cells";
	}

	bound_other_ammo (other);

	// Discard backpacks do their own printing
	if (self.weapon > 0)
	{
		quantity = ftos(self.aflag);
		sprint(other, PRINT_LOW, "You picked up ", quantity, " ", self.netname, "\n");
	}

	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
	stuffcmd (other, "bf\n");

	dremove(self);
	self = other;
	W_SetCurrentAmmo();
};

// Return the number of pipebombs in existence for a particular team
float (float tno) num_team_ammoboxes =
{
	if (tno == 1)
		return num_team_ammoboxes_1;
	else if (tno == 2)
		return num_team_ammoboxes_2;
	else if (tno == 3)
		return num_team_ammoboxes_3;
	else if (tno == 4)
		return num_team_ammoboxes_4;

	return 0;
};

// Remove enough old ammoboxes to bring the count down to the max level
void(float tno) RemoveOldAmmobox =
{
	local entity old;
	local float index;

	if (tno != 0)
	{
		index = num_team_ammoboxes(tno);
		index = index - (MAX_WORLD_AMMOBOXES / number_of_teams);
	}
	else
	{
		index = num_world_ammoboxes - MAX_WORLD_AMMOBOXES;
	}

	old = find(NIL, classname, "ammobox");
	while (index > 0)
	{
		if (!old)
		{
//			RPrint("*** ERROR: RemoveOldAmmobox. ***\n");
//			RPrint("*** Shaka thought he fixed this ***\n");
			num_world_ammoboxes = num_world_ammoboxes - 1;
			decrement_team_ammoboxes(old.team_no);
			return;
		}

		if (old.team_no == tno || tno == 0)
		{
			old.think = SUB_Remove;
			old.nextthink = time + 0.1;
			index = index - 1;

			num_world_ammoboxes = num_world_ammoboxes - 1;
			decrement_team_ammoboxes(old.team_no);
		}

		old = find(old, classname, "ammobox");
	}
};

void(float tno) increment_team_ammoboxes =
{
	if (tno == 1)
		num_team_ammoboxes_1 = num_team_ammoboxes_1 + 1;
	else if (tno == 2)
		num_team_ammoboxes_2 = num_team_ammoboxes_2 + 1;
	else if (tno == 3)
		num_team_ammoboxes_3 = num_team_ammoboxes_3 + 1;
	else if (tno == 4)
		num_team_ammoboxes_4 = num_team_ammoboxes_4 + 1;
};

void(float tno) decrement_team_ammoboxes =
{
	if (tno == 1)
		num_team_ammoboxes_1 = num_team_ammoboxes_1 - 1;
	else if (tno == 2)
		num_team_ammoboxes_2 = num_team_ammoboxes_2 - 1;
	else if (tno == 3)
		num_team_ammoboxes_3 = num_team_ammoboxes_3 - 1;
	else if (tno == 4)
		num_team_ammoboxes_4 = num_team_ammoboxes_4 - 1;
};

//=========================================================================
// WEAPON HANDLING FUNCTIONS
//=========================================================================
//=========================================================================
// Assault Cannon selection function
void() TeamFortress_AssaultWeapon =
{
	self.impulse = 0;

    if (self.tfstate & TFSTATE_RELOADING)
   		return;

	if (!(self.weapons_carried & WEAP_ASSAULT_CANNON)) 
		return;

	if (self.heat > 0)
	{
		sprint (self, PRINT_HIGH, "the assault cannon is still overheated.\n");
		return;
	}

	if (self.ammo_shells < 1)
	{	// don't have the ammo
		sprint (self, PRINT_HIGH, "not enough ammo.\n");
		return;
	}
	// The cannon also needs 6 cells to power up 
	if (self.ammo_cells < 6)
	{
		sprint (self, PRINT_HIGH, "not enough cells to power the assault cannon.\n");
		return;
	}

	self.current_weapon = WEAP_ASSAULT_CANNON;

	W_SetCurrentAmmo ();
};

//=========================================================================
// If this gets called, the players holding onto an exploding grenade :)
void() TeamFortress_ExplodePerson =
{
	// Removes the owners grenade
	self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_GRENPRIMED);

	KickPlayer(-2, self.owner);

	newmis = spawn ();
	newmis.movetype = MOVETYPE_BOUNCE;
	newmis.solid = SOLID_BBOX;
	newmis.classname = "grenade";
	newmis.team_no = self.owner.team_no;
	newmis.owner = self.owner;
		
	// Don't bother calculating a velocity
	newmis.velocity = '0 0 0';
	newmis.angles = vectoangles(newmis.velocity);
	
	// set the grenades thinktime to now
	newmis.think = dont_think;
	newmis.nextthink = time + 0.1;

	// set the think and touches to the appropriate grenade type
	if (self.weapon == GR_TYPE_NORMAL)
	{
		newmis.touch = NormalGrenadeTouch;
		newmis.think = NormalGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
	else if (self.weapon == GR_TYPE_CONCUSSION)
	{
		newmis.touch = ConcussionGrenadeTouch;
		newmis.think = ConcussionGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
    else if (self.weapon == GR_TYPE_BIO)
	{
		newmis.touch = BioGrenadeTouch;
		newmis.think = BioGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
	else if (self.weapon == GR_TYPE_ANTIGRAV)
	{
		newmis.touch = ConcussionGrenadeTouch;
		newmis.think = AntiGravGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
	else if (self.weapon == GR_TYPE_NAIL)
	{
		newmis.touch = NailGrenadeTouch;
		newmis.think = NailGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '0 300 0';
		setmodel (newmis, "progs/biggren.mdl");
	}
   	else if (self.weapon == GR_TYPE_CALTROP)
	{
		newmis.touch = NormalGrenadeTouch;
		newmis.think = CaltropGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/hgren2.mdl");
	}
	else if (self.weapon == GR_TYPE_MIRV)
	{
		newmis.touch = MirvGrenadeTouch;
		newmis.think = MirvGrenadeExplode;
		newmis.skin = 0;
		newmis.avelocity = '0 300 0';
		setmodel (newmis, "progs/biggren.mdl");
	}
	else if (self.weapon == GR_TYPE_NAPALM)
	{
		newmis.touch = NapalmGrenadeTouch;
		newmis.think = NapalmGrenadeExplode;
		newmis.skin = 2;
		newmis.avelocity = '0 300 0';
		setmodel (newmis, "progs/biggren.mdl");
	}
//CH no flare 
//OfN why??
	else if (self.weapon == GR_TYPE_FLARE)
	{
		//sprint(self.owner, PRINT_HIGH, "Flare lit.\n");
        sprint(self.owner, PRINT_HIGH, "The flare burns on your hand!\n");
		T_Damage(self.owner, self.owner, self.owner,12);
        stuffcmd(self.owner, "bf\nbf\n");

        newmis.touch = FlareBounce;
		newmis.think = FlareGrenadeExplode;
		newmis.skin = 0;
        newmis.has_holo=1;
		newmis.avelocity = '0 0 0';
		setmodel (newmis, "progs/flarefly.mdl");

        /*te = spawn();
   		te.touch = NIL;
		te.think = SUB_Remove;//FlareGrenadeExplode;//RemoveFlare;
		te.nextthink = time + 25;
		te.owner = self.owner;
		te.solid = SOLID_NOT;
		self.owner.effects = self.owner.effects | EF_BRIGHTLIGHT;*/

    	setsize (newmis, '0 0 0', '0 0 0');		
	    setorigin (newmis, self.owner.origin);

        
        dremove(self);
		//dremove(newmis);
		return;
	}
	else if (self.weapon == GR_TYPE_GAS)
	{
		newmis.touch = GasGrenadeTouch;
		newmis.think = GasGrenadeExplode;
		newmis.skin = 2;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/grenade2.mdl");
	}
	else if (self.weapon == GR_TYPE_EMP)
	{
		newmis.touch = EMPGrenadeTouch;
		newmis.think = EMPGrenadeExplode;
		newmis.skin = 4;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/grenade2.mdl");
	}
	else if (self.weapon == GR_TYPE_FLASH)
	{
		newmis.touch = FlashGrenadeTouch;
		newmis.think = FlashGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/grenade2.mdl");
	}
	else if (self.weapon == GR_TYPE_FRAG)
	{
		newmis.touch = FragGrenadeTouch;
		newmis.think = FragGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/grenade2.mdl");
	}
	else if (self.weapon == GR_TYPE_KRAC)
	{
		newmis.touch = KracGrenadeTouch;
		newmis.think = KracGrenadeExplode;
		newmis.skin = 1;
		newmis.avelocity = '300 300 300';
		setmodel (newmis, "progs/grenade2.mdl");
	}

	setsize (newmis, '0 0 0', '0 0 0');		
	setorigin (newmis, self.owner.origin);

	//bprint(PRINT_MEDIUM, "No ");
	//bprint(PRINT_MEDIUM, self.owner.netname);
	//bprint(PRINT_MEDIUM, ", throw the grenade, not the pin!\n");

	bprint(PRINT_MEDIUM, "No ");
	bprint(PRINT_MEDIUM, self.owner.netname);
	bprint(PRINT_MEDIUM, ", you are supposed to THROW the grenade!\n");

    //no xxx, your grenade is your friend for another reason!
    //no

	// Remove primed grenade object	
	dremove(self);
};

//=========================================================================
// Thrown Grenade touch function.
void() NormalGrenadeTouch =
{
	if (other == self.owner)
		return;		// don't explode on owner

	// Thrown grenades don't detonate when hitting an enemy

	sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);	// bounce sound
	if (self.velocity == '0 0 0')
		self.avelocity = '0 0 0';
};

//=========================================================================
// Thrown grenade explosion. 50% more powerful as grenade launcher grenades.
void() NormalGrenadeExplode =
{
	deathmsg = DMSG_GREN_HAND;
	T_RadiusDamage (self, self.owner, 180, NIL);

#ifdef DEMO_STUFF
	// Remove any camera's locks on this missile
	if (self.enemy)
		CamProjectileLockOff();
#endif

	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
	WriteCoord (MSG_MULTICAST, self.origin_x);
	WriteCoord (MSG_MULTICAST, self.origin_y);
	WriteCoord (MSG_MULTICAST, self.origin_z);
	multicast (self.origin, MULTICAST_PHS);
	dremove(self);
};

//=========================================================================
// Displays the state of the items in the Detection Entity
void() TeamFortress_DisplayDetectionItems =
{
	local entity Goal, te;

	Goal = find(NIL, classname, "info_tfdetect");
	if (!Goal)
		return;

	// Check to make sure they've got some strings
	if (!Goal.team_str_home)
		return;

	if (Goal.display_item_status1 != 0)
	{
		te = Finditem(Goal.display_item_status1);
		if (te)
			DisplayItemStatus(Goal, self, te);
		else
			sprint (self, PRINT_HIGH, "Item is missing.\n");
	}
	else
		return;

	if (Goal.display_item_status2 != 0)
	{
		te = Finditem(Goal.display_item_status2);
		if (te)
			DisplayItemStatus(Goal, self, te);
		else
			sprint (self, PRINT_HIGH, "Item is missing.\n");
	}
	else
		return;

	if (Goal.display_item_status3 != 0)
	{
		te = Finditem(Goal.display_item_status3);
		if (te)
			DisplayItemStatus(Goal, self, te);
		else
			sprint (self, PRINT_HIGH, "Item is missing.\n");
	}
	else
		return;

	if (Goal.display_item_status4 != 0)
	{
		te = Finditem(Goal.display_item_status4);
		if (te)
			DisplayItemStatus(Goal, self, te);
		else
			sprint (self, PRINT_HIGH, "Item is missing.\n");
	}
};

//=========================================================================
// ITEM HANDLING FUNCTIONS
//=========================================================================
// Function for handling the BioInfection Decay of players
void() BioInfection_Decay =
{
	// Remove infections which can't hurt the owner
	if ((teamplay & TEAMPLAY_NOEXPLOSIVE) && Teammate(self.owner.team_no,self.enemy.team_no))
	{
		self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_INFECTED);
		dremove(self);
		return;
	}

	if (self.invincible_finished > time)
	{
		self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_INFECTED);
		dremove(self);
		return;
	}

	if (self.owner.current_weapon == WEAP_MEDIKIT)
	{
		sprint(self.owner,PRINT_HIGH,"You heal yourself of your infection.\n");
		self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_INFECTED);
		dremove(self);
		return;
	}
	self.nextthink = time + 2;

	deathmsg = DMSG_BIOWEAPON;
	TF_T_Damage(self.owner, self, self.enemy, 5, TF_TD_IGNOREARMOUR, TF_TD_OTHER);

	SpawnBlood(self.owner.origin, 30);

	// remove this entity if the infection is gone
	if ( !(self.owner.tfstate & TFSTATE_INFECTED) )
		dremove(self);
};

//========================================================================
// Function for handling the BioInfection Decay of monsters
void() BioInfection_MonsterDecay =
{
	local float drmg;

	if (!(self.enemy.tfstate & TFSTATE_INFECTED)) {
		dremove(self);
		return;
	}

	drmg = 200 * random();
	drmg = drmg * random();

	self.nextthink = time + 2;

	T_Damage(self.enemy, self, self.owner, drmg);
	SpawnBlood(self.enemy.origin, drmg+10);
	
	if (self.enemy.health < 1)
		dremove(self);
		
};

//=========================================================================
// UTILITY FUNCTIONS
//=========================================================================
// Stuff an alias. This is a little messy since we insisted
// on maintaining the ability to alter the impulse numbers in the defs.qc 
// and not have to change any code. 
void(string halias, float himpulse1, float himpulse2) TeamFortress_Alias =
{
	local string imp;

	stuffcmd(self, "alias ");
	stuffcmd(self, halias);
	stuffcmd(self, " \"impulse ");
	imp = ftos(himpulse1);
	stuffcmd(self, imp);

	// if himpulse2 is not zero, assume that himpulse1 is a preimpulse 
	// and complete the alias
	if (himpulse2 != 0)
	{
		stuffcmd(self, ";wait; impulse ");
		imp = ftos(himpulse2);
		stuffcmd(self, imp);
	}
	stuffcmd(self, "\"\n");
};

//=========================================================================
// CYCLIC EVENT FUNCTIONS
//=========================================================================
//=========================================================================
// Regenerates the entity which owns this cyclictimer
void() TeamFortress_Regenerate =
{
//WK	if (self.owner.playerclass == PC_MEDIC)
	if (self.is_abouttodie)
		return;
	if (self.owner.weapons_carried & WEAP_MEDIKIT) //WK Custom class friendly
	{
		self.nextthink = time + PC_MEDIC_REGEN_TIME;

		if (self.owner.health >= self.owner.max_health)
			return;

		if (self.owner.ammo_medikit == 0)
			return;

		if (self.owner.ammo_medikit < PC_MEDIC_REGEN_AMOUNT)
		{
			self.owner.health = self.owner.health + self.owner.ammo_medikit;
			self.owner.ammo_medikit = 0;
		}
		else
		{
			self.owner.health = self.owner.health + PC_MEDIC_REGEN_AMOUNT;
			self.owner.ammo_medikit = self.owner.ammo_medikit - PC_MEDIC_REGEN_AMOUNT;
		}

		if (self.owner.health > self.owner.max_health)
			self.owner.health = self.owner.max_health;
	}
};

void() CyberAugSleep =
{
	if (self.owner.velocity_z == 0 && self.owner.velocity_y == 0 && self.owner.velocity_x == 0)
		self.think = TeamFortress_RegenerateCyber;
	
	self.nextthink = time + 2;
};

void() TeamFortress_RegenerateCyber =
{
	if (self.is_abouttodie)
		return;
	
//WK	if (self.owner.playerclass == PC_MEDIC)
	if (self.owner.velocity_z > 0 || self.owner.velocity_y > 0 || self.owner.velocity_x > 0)
	{
		self.nextthink = time + 2;
		self.think = CyberAugSleep;
		return;
	}

	if (self.owner.cutf_items & CUTF_CYBERAUG && !(self.owner.is_malfunctioning)) //WK Custom class friendly
	{
		self.owner.armortype = self.owner.armor_allowed;
		W_SetCurrentAmmo();
		if (self.owner.health < self.owner.max_health)
		{
			if (self.owner.ammo_medikit == 0)
				self.owner.health = self.owner.health + 1;
			else if (self.owner.ammo_medikit < PC_MEDIC_REGEN_AMOUNT / 2.0)
			{
				self.owner.health = self.owner.health + self.owner.ammo_medikit * 2;
				self.owner.ammo_medikit = 0;
			}
			else
			{
				self.owner.health = self.owner.health + PC_MEDIC_REGEN_AMOUNT;
				self.owner.ammo_medikit = self.owner.ammo_medikit - PC_MEDIC_REGEN_AMOUNT / 2.0;
			}
		}
		
		if (self.owner.armorvalue < self.owner.maxarmor)
		{
			if (self.owner.ammo_cells == 0)
				self.owner.armorvalue = self.owner.armorvalue + 2;
			else if (self.owner.ammo_cells < PC_MEDIC_REGEN_AMOUNT)
			{
				self.owner.armorvalue = self.owner.armorvalue + self.owner.ammo_cells * 2;
				self.owner.ammo_cells = 0;
			}
			else
			{
				self.owner.armorvalue = self.owner.armorvalue + PC_MEDIC_REGEN_AMOUNT * 2;
				self.owner.ammo_cells = self.owner.ammo_cells - PC_MEDIC_REGEN_AMOUNT;
			}
		}

        UpdateCells(self.owner);

		if (self.owner.armorvalue > self.owner.maxarmor)
			self.owner.armorvalue = self.owner.maxarmor;
		if (self.owner.health > self.owner.max_health)
			self.owner.health = self.owner.max_health;
	}
	else if (self.owner.cutf_items & CUTF_CYBERAUG && self.owner.is_malfunctioning == 1)
	{
		if (self.owner.health > 3)
			TF_T_Damage(self.owner, self.owner, self.owner, 3, TF_TD_IGNOREARMOUR, TF_TD_OTHER);
		else if (self.owner.health < 3 && self.owner.health > 1)
			self.owner.health = 1;
		if (self.owner.armorvalue > 3)
			self.owner.armorvalue = self.owner.armorvalue - 3;
		else if (self.owner.armorvalue < 3)
			self.owner.armorvalue = 0;
	}
	
	self.nextthink = time + PC_MEDIC_REGEN_TIME;

};
//=========================================================================
// Activates when we go hidden
// If we're moving, make us not invis
void() TeamFortress_RegenerateCells =
{
	//WK Borrow this code from TF, since there's no reason to
	// duplicate it.
	if (!(self.owner.job & JOB_THIEF))
		dremove(self);
	if (!(self.owner.job & JOB_ACTIVE))
		dremove(self);
	if (self.owner.health <= 0)
		dremove(self);
	self.nextthink = time + PC_SPY_CELL_REGEN_TIME;
	if (self.owner.job & JOB_ACTIVE)
	{
		/*if (self.owner.ammo_cells == 0)
		{
			RevealThief(self.owner,FALSE);
		}
		else 	*/		
			//if (self.owner.ammo_cells > 100) self.owner.ammo_cells = 100;
		if ((self.owner.velocity_z > 0 || self.owner.velocity_y > 0 || self.owner.velocity_x > 0) && self.owner.job & JOB_FULL_HIDE)
		{
				self.owner.frame = 0;
				self.owner.weaponframe = 0;
				self.owner.modelindex = modelindex_eyes;
				self.owner.job = self.owner.job - (self.owner.job & JOB_FULL_HIDE);
				TeamFortress_SetSpeed(self.owner);
			/*self.owner.ammo_cells = self.owner.ammo_cells - PC_SPY_CELL_USAGE;
			if (self.owner.ammo_cells <= 0) {
				self.owner.ammo_cells = 0;
				RevealThief(self.owner,FALSE);
			}*/
		}
		else if ((self.owner.velocity_z == 0 && self.owner.velocity_y == 0 && self.owner.velocity_x == 0)
				 && !(self.owner.job & JOB_FULL_HIDE)
				 && !(self.effects & (EF_DIMLIGHT | EF_BRIGHTLIGHT)))
		{
			self.owner.frame = 0;
			self.owner.weaponframe = 0;
			self.owner.modelindex = modelindex_null;
			self.owner.job = self.owner.job | JOB_FULL_HIDE;
		}
	}
	/*else	// Increase cell ammo
	{
		if (self.owner.ammo_cells >= self.owner.maxammo_cells)
			return;

		self.owner.ammo_cells = self.owner.ammo_cells + PC_SPY_CELL_REGEN_AMOUNT;

		if (self.owner.ammo_cells > self.owner.maxammo_cells)
			self.owner.ammo_cells = self.owner.maxammo_cells;
	}*/
	//return;

	/*
	if (self.owner.playerclass == PC_SPY)
	{
		self.nextthink = time + PC_SPY_CELL_REGEN_TIME;

		// If the spy is undercover, decrease the number of cells
		if (self.owner.is_undercover == 1)
		{
			// If the spy has no cells left, he becomes visible again
			if (self.owner.ammo_cells == 0)
			{
				self.owner.is_undercover = 0;
				self.owner.modelindex = modelindex_player;	// return to normal
				self.owner.items = self.owner.items & ~IT_INVISIBILITY;
			}
			else // Decrease cells
			{
				self.owner.ammo_cells = self.owner.ammo_cells - PC_SPY_CELL_USAGE;
				if (self.owner.ammo_cells < 0)
					self.owner.ammo_cells = 0;
			}
		}
		else	// Increase cell ammo
		{
			if (self.owner.ammo_cells >= self.owner.maxammo_cells)
				return;

			self.owner.ammo_cells = self.owner.ammo_cells + PC_SPY_CELL_REGEN_AMOUNT;

			if (self.owner.ammo_cells > self.owner.maxammo_cells)
				self.owner.ammo_cells = self.owner.maxammo_cells;
		}

		return;
	}
	*/
};

//============================================================================
// sends a player to observer mode
void() PlayerObserverMode =
{
	DetonateAllGuns();
	kill_my_demon();
	self.current_menu = MENU_DEFAULT;
	self.impulse = 0;
	self.playerclass = PC_UNDEFINED;
	self.lives = 0;
	self.health = 1;
	self.gravity = 0; //WK Make em float so prediction doesn't get all annoying-like
	if (self.team_no > 0) self.old_team_no = self.team_no; //WK Save old team for scoreboard
	self.team_no = -1;

	self.flags = FL_CLIENT | FL_NOTARGET | FL_ONGROUND;
	self.waterlevel = 3;
	self.takedamage = DAMAGE_NO;
	self.solid = SOLID_NOT;
	//self.movetype = MOVETYPE_NOCLIP;
	self.movetype = MOVETYPE_FLY;

	self.model = "";
	self.mdl = "";
	setmodel(self, "");

	self.velocity = '0 0 0';
	self.avelocity = '0 0 0';

	sprint (self, PRINT_HIGH, "Observer mode\n");
	CenterPrint(self, "\n");
	SetPlayerColor (self, 0, 0);
	stuffcmd(self, "cl_rollangle 0\n"); // FIXME: does this need a wait?
};

//============================================================================
// Return the crossproduct of 2 vectors
vector(vector veca, vector vecb) crossproduct =
{
	local vector result;

	result_x = (veca_y * vecb_z) - (vecb_y * veca_z);
	result_y = (veca_z * vecb_x) - (vecb_z * veca_x);
	result_z = (veca_x * vecb_y) - (vecb_x * veca_y);
	return result;
};