Created By: Kryten
eMail: kryten@inside3d.com
Difficulty Scale: Normal


In Quake there is not much of a difference between hard skill and nightmare skill. This nightmare, toughest of the tough skill is only a little harder than the hard skill. And as long as you can just cheat to get out of and tough situation it might as well be easy skill. This tutorial will show you how to disable cheating in nightmare, but still allow those llamas that cant play to still cheat in easy skill.

Easy skill is skill 0, makes since, if you have no skill then just go to easy. Normal is 1, better than no skill at all at least. Hard is 2, this is the skill that real people play at. And Nightmare is 3, third is only slightly harder than Hard, but still id hid the entrance to it. In this tutorial I use "!= 3" to allow users to still cheat in every skill but Nightmare, however, you can change that too "== 0" to allow cheating only in easy.

Step 1, In this step we will take care of God mode. Start by opening up the Combat.qc and going to the T_Damage function and find these lines:

// figure momentum add
	if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
	{
		dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
		dir = normalize(dir);
		targ.velocity = targ.velocity + dir*damage*8;
	}

// check for godmode or invincibility
	if (targ.flags & FL_GODMODE)
		return;
Now move them up to just below these line, I will tell you why in just a sec.

// check for quad damage powerup on the attacker
	if (attacker.super_damage_finished > time)
		damage = damage * 4;
That makes it check for god mode earlier and does not take away armor if you are using god mode, but the player will still be pushed back a little by nails, rockets, and other projectiles. This means the physics will always act the same with or without god mode. Now make a change to the FL_GODMODE line, this is what I want you to change it to:

// check for godmode or invincibility
	if ((targ.flags & FL_GODMODE) && (skill != 3))
		return;
Thats it for god mode, very simple.

Step 2, Now we will take care of notarget, the cheat that allows you to remain invisible to all monsters. This is the same effect as having the ring of shadows. To take care of this start by opening the Ai.qc and going down to FindTarget, there you need to find these lines:

	if (client.flags & FL_NOTARGET)
		return FALSE;
Simply change them to this:

	if ((client.flags & FL_NOTARGET) && (skill != 3))
		return FALSE;
Now go to the Monsters.qc and find this line in the monster_use function:

	if (activator.flags & FL_NOTARGET)
		return;
Make this simple change:

	if ((activator.flags & FL_NOTARGET) && (skill != 3))
		return;
Step 3, Now we take care of impulse 9, impulse 11, and impulse 255. Open the Weapons.qc and go down to the ImpulseCommands function, and find these lines:

	if (self.impulse == 9)
		CheatCommand ();
...
	if (self.impulse == 11)
		ServerflagsCommand ();
...
	if (self.impulse == 255)
		QuadCheat ();
Change those lines to these:

	if ((self.impulse == 9) && (skill != 3))
		CheatCommand ();
...
	if ((self.impulse == 11) && (skill != 3))
		ServerflagsCommand ();
...
	if ((self.impulse == 255) && (skill != 3))
		QuadCheat ();
Step 4, now this step is the hardest, it takes care of Fly mode, Noclip mode, and the give commands. Start by adding this to the top of PlayerPostThink in the client.qc:

	CheckCheat ();
Above the PlayerPostThink function add this new function:

/*
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
CheckCheat

disables fly mode, noclip mode, and give commands

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
*/ 
void () CheckCheat =
{
	if (skill != 3)
		return;

	self.movetype = MOVETYPE_WALK;

	self.health = self.real_health;
	self.items = self.real_items;
	self.ammo_shells = self.real_ammo_shells;
	self.ammo_nails = self.real_ammo_nails;
	self.ammo_rockets = self.real_ammo_rockets;
	self.ammo_cells = self.real_ammo_cells;

	W_SetCurrentAmmo ();
};
This sets the movetype to walk and sets health, items and ammo back to the real settings, preventing the use of the give command. Now you need to take care of setting the real_ammo_ etc. whenever the player gets items, health, or ammo.

Now you need to defing all these new fields in the Defs.qc, so at the bottom of that file add:

.float real_health, real_items, real_ammo_shells, real_ammo_nails, real_ammo_rockets, real_ammo_cells;
The main work now is just setting the real_ values. So open the Items.qc and go to the bottom of the health_touch and add these lines:

	other.real_health = other.health;
	other.real_items = other.items;
In the item_megahealth_rot find this line:

		other.health = other.health - 1;
change it to:

		other.real_health = other.health = other.health - 1;
then add add this line at the bottom:

	other.real_items = other.items;
Now go to the armor_touch function and add this to the bottom:

	other.real_items = other.items;
In the bound_other_ammo function add this to the bottom:

	self.real_ammo_shells = self.ammo_shells;
	self.real_ammo_nails = self.ammo_nails;
	self.real_ammo_rockets = self.ammo_rockets;
	self.real_ammo_cells = self.ammo_cells;
Find this line in the weapon_touch function:

	other.items = other.items | new;
and change it to this:

	other.real_items = other.items = other.items | new;
At the bottom of key_touch, powerup_touch, and BackpackTouch add this line:

	other.real_items = other.items;
In the Weapons.qc find the function, W_SetCurrentAmmo, CheatCommand, and QuadCheat, and add this line at the bottom of those functions:

	self.real_items = self.items;
Add this line to bottom for the door_touch function in the Doors.qc:

	other.real_items = other.items;
And finally in the Client.qc find the DecodeLevelParms function. At the bottom add:

	self.real_items = self.items;
	self.real_health = self.health;
	self.real_ammo_shells = self.ammo_shells;
	self.real_ammo_nails = self.ammo_nails;
	self.real_ammo_rockets = self.ammo_rockets;
	self.real_ammo_cells = self.ammo_cells;
UPDATE: I forgot to add this step, and without it the player will never die. Open the Combat.qc and go down to the T_Damage function. Find this line:

// do the damage
	targ.health = targ.health - take;
Change it to this:

// do the damage
	targ.real_health = targ.health = targ.health - take;
Now you can compile and the user can no longer cheat in nightmage skill.