Experience Systems
Created By: Marius
eMail: lordshoel@yahoo.com
Difficulty Scale: Medium


This tutorial will introduce two different Experience Systems to Quake. The first method or system is Points By Kills as I call it. This system gives you a certain amount of Exp Points per death and is relational to the monster type killed. The second method or system is what I call Points Per Blow. Despite the name it has nothing to do with lewd activities but rather is an Exp System by which for each time you hit a monster you gain a small amount of experience. In this system it depends upon weapon and monster to the value of experience recieved. Each method is outlined seperately. The first method is the easiest though I suggest the second as a more 'hardcore' approach.

Method 1: Points By Kills
Step 1.

Open up Defs.qc and scroll down to the very bottom and add:

//Variable for Exp Total
.float has_exp;	
This is the variable that stores our total experience points. You may wish to change the name but if you do remember to do it in all the steps. Go on to the next step.

Step 2.

Ok, the first step in either method is to create a new QC file called Exp_Sys.qc. Into this new file add the following:

/*
==============================================================================

EXPERIENCE SYSTEM A - POINTS PER KILL

==============================================================================
*/

void(entity person, float expamt) AddExp =
{
	local string tally;

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

	person.has_exp = person.has_exp + expamt;	

	tally = ftos(person.has_exp);

	if (person.classname == "player")
	{
		sprint(person, "You now have ");
		sprint(person, tally);
		sprint(person, " Experience Points\n");
	}

};
This function tallys up the experience and prints the amount the person has.

Step 3.

Now that the above step is complete and the Exp Function is in place we need to make use of it. Open up Combat.qc and scroll down to the Killed function. Found it? Once you've found it find the lines within it that look like this:

	if (self.flags & FL_MONSTER)
	{
		killed_monsters = killed_monsters + 1;
		WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
	}
This is where well the Exp System comes in to use. Replace the above block of code with the below:

	if (self.flags & FL_MONSTER)
	{
		killed_monsters = killed_monsters + 1;
		if (self.classname == "monster_dog") AddExp (attacker, 30);
		if (self.classname == "monster_knight") AddExp (attacker, 50);
		if (self.classname == "monster_zombie") AddExp (attacker, 55);
		if (self.classname == "monster_demon1") AddExp (attacker, 70);
		if (self.classname == "monster_fish") AddExp (attacker, 20);
		if (self.classname == "monster_enforcer") AddExp (attacker, 40);
		if (self.classname == "monster_hell_knight") AddExp (attacker, 75);
		if (self.classname == "monster_ogre") AddExp (attacker, 65);
		if (self.classname == "monster_ogre_marksman") AddExp (attacker, 65);
		if (self.classname == "monster_shalrath") AddExp (attacker, 60);
		if (self.classname == "monster_shambler") AddExp (attacker, 80);
		if (self.classname == "monster_army") AddExp (attacker, 35);
		if (self.classname == "monster_tarbaby") AddExp (attacker, 25);
		if (self.classname == "monster_wizard") AddExp (attacker, 45);
		WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
	}
Done that? If so continue to the next step.

Step 4.

The following step is optional. If you do not wish to have a key to press to display your Experince Points then go onto step 5. If you do then open up Exp_sys.qc and below the AddExp function add the following code:

void() PrintExp =
{
	local string tally;

	tally = ftos(self.has_exp);

	if (person.classname == "player")
	{
		sprint(self, "You now have ");
		sprint(self, tally);
		sprint(self, " Experience Points\n");
	}

};
Now open up Weapons.qc and find ImpulseCommands. In this function above the impulse for QuadCheat add the following impulse:

	if (self.impulse = 15) PrintExp ();
All you have to do is bind the impulse, in this case 15 to a key in quake or edit the config file.

Step 5.

This is the easiest step. Open up Progs.src and above Combat.qc add Exp_sys.qc. Now save everything and compile. Pat yourself on the back cause your finished.

Method 2: Points By Blows
Step 1.

Open up Defs.qc and scroll down to the very bottom and add:

//Variable for Exp Total
.float has_exp;	
This is the variable that stores our total experience points. You may wish to change the name but if you do remember to do it in all the steps. Go on to the next step.

Step 2.

Ok, the first step in either method is to create a new QC file called Exp_Sys.qc. Into this new file add the following:

/*
==============================================================================

EXPERIENCE SYSTEM B - POINTS PER BLOW

==============================================================================
*/

void(entity person, float expamt) AddExp =
{
	local string tally;

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

      if (self.weapon == IT_AXE)expamt = expamt * 2;
      else if (self.weapon == IT_SHOTGUN)expamt = expamt * 1.7;
      else if (self.weapon == IT_SUPER_SHOTGUN)expamt = expamt * 1;
      else if (self.weapon == IT_NAILGUN)expamt = expamt * 1.2;
      else if (self.weapon == IT_SUPER_NAILGUN)expamt = expamt * 1;
      else if (self.weapon == IT_GRENADE_LAUNCHER)expamt = expamt * 0.8;
      else if (self.weapon == IT_ROCKET_LAUNCHER)expamt = expamt * 0.7;
      else if (self.weapon == IT_LIGHTNING)expamt = expamt * 0.5;

	person.has_exp = person.has_exp + expamt;	
};

void(entity person) PrintExp =
{
	local string tally;

	tally = ftos(person.has_exp);

	if (person.classname == "player")
	{
		sprint(person, "You now have ");
		sprint(person, tally);
		sprint(person, " Experience Points\n");
	}

};
This function tallys up the experience and prints the amount the person has.

Step 3.

This step puts the AddExp function to use. So open up Combat.qc and scroll down to the T_Damage function. After block beginning with the lines:

// check for godmode or invincibility
	if (targ.flags & FL_GODMODE)
Add the following block of code:

		if (self.classname == "monster_dog") AddExp (attacker, 3);
		if (self.classname == "monster_knight") AddExp (attacker, 5);
		if (self.classname == "monster_zombie") AddExp (attacker, 5);
		if (self.classname == "monster_demon1") AddExp (attacker, 7);
		if (self.classname == "monster_fish") AddExp (attacker, 2);
		if (self.classname == "monster_enforcer") AddExp (attacker, 4);
		if (self.classname == "monster_hell_knight") AddExp (attacker, 7);
		if (self.classname == "monster_ogre") AddExp (attacker, 6);
		if (self.classname == "monster_ogre_marksman") AddExp (attacker, 6);
		if (self.classname == "monster_shalrath") AddExp (attacker, 6);
		if (self.classname == "monster_shambler") AddExp (attacker, 80);
		if (self.classname == "monster_army") AddExp (attacker, 3);
		if (self.classname == "monster_tarbaby") AddExp (attacker, 2);
		if (self.classname == "monster_wizard") AddExp (attacker, 4);
Now above the in the Killed function within the block of code:

	if (self.flags & FL_MONSTER)
	{
		killed_monsters = killed_monsters + 1;
		WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
	}
Add the line above or below killed_monsters:

	PrintExp(attacker);
No thats all for Combat.qc. What we have done is set the base amount of Exp for each monster. Also we have made it so when you kill a monster it prints the Experience Points total rather than at each blow.

Step 4.

Now open up Weapons.qc and find ImpulseCommands. In this function above the impulse for QuadCheat add the following impulse:

	if (self.impulse = 15) PrintExp (self);
All you have to do is bind the impulse, in this case 15 to a key in quake or edit the config file.

Step 5.

This is the easiest step. Open up Progs.src and above Combat.qc add Exp_sys.qc. Now save everything and compile. Pat yourself on the back cause your finished.

Afterword
Well there you go. Two different Experience Systems. Is that choice or what. Use which one best suits you. Now to be serious, there are several alterations you could make to these Exp Systems and they vary on your personal choice. You may wish to change the amounts received for each monster and the alteration to the base for each monster in the second Exp System. If you use this please give me credit for it. Also if you find any bugs let me know and I'll fix them.
Marius