Created By: Kryten
Difficulty Scale: Medium

In this tutorial we will be taking some swimming lessons! We will make the player look like he is swimming while underwater. To do this we will use new swimming frames and adjust the player angles to make this look real! This would be a great addition to any Quake MOD, especially deathmatch mods!

First download the new model with swimming frames from here.

Open your world.qc and go down to this:

// player precaches 
W_Precache (); // get weapon precaches

Then after that add this:

precache_model ("progs/playswim.mdl");

Now open your client.qc. Under this line:

float modelindex_eyes, modelindex_player;

add these two lines:

float modelindex_swimmer; //Kryten: swimmer
void () player_swim_angles; //adjust the player angles for swimming

Now go down to the PutClientInServer function, in that function under:

	// oh, this is a hack!
	setmodel (self, "progs/eyes.mdl");
	modelindex_eyes = self.modelindex;

add these lines:

	//don't you just love hacks! this is our swimming model
	setmodel (self, "progs/playswim.mdl");
	modelindex_swimmer = self.modelindex;

Now go down to the CheckPowerups and change these lines:

		self.modelindex = modelindex_player; // don't use eyes

Change them to this:

//if under water don't use player model: if firing we will change back to player for just a sec.
		if ((self.waterlevel < 3) || (self.button0))
			self.modelindex = modelindex_player; // don't use eyes
We only have one more thing to do in this file. Go to the bottom of player_postthink and add these lines:

	if (self.waterlevel == 3)

Now save changes and exit. Open your player.qc file now. Just above:

void() player_stand1 =[ $axstnd1, player_stand1 ]

add this function

void () player_swim_angles =
{ //this will adjust the player angles to make swimming look real
	self.angles = vectoangles(v_forward);

	if (self.velocity_x) //FIXME: does not seem to work correctly while underwater
		self.angles_x = self.angles_x - 90;

Notice the FIXME. It seems that while underwater Quake can sometimes think you are moving when you are not. I don't know why this is, but it seems that if you are moving and stop moving you have to hit the bottom before Quake knows that you are not moving foward. Just under that function add this function:

void () player_swim = [ 0, player_swim ]
{ //Kryten: there goes my hero; watch him as he swims
	if (self.waterlevel < 3)
		{self.walkframe = 0; player_run(); return; }

	if (!self.invisible_finished)
		self.modelindex = modelindex_swimmer; // reset model just in case

	if (self.walkframe >= 17)
		self.walkframe = 0;
	self.frame = 0 + self.walkframe;
	self.walkframe = self.walkframe + 1; 

That's our swimming function, it will make the player look like he is swimming! Now we need to make our swimming function get called. Go down just a little and in the player_stand1 function just under:


we want to add this:

	if (self.waterlevel == 3)
		{ player_swim (); return; }

and just do the same in the player_run. Now we have only more more thing to do. Go down to player_pain and just under:

	if (self.invisible_finished > time)
		return; // eyes don't have pain frames

add this:

//Kryten: in case we are swimming change back to player model go into pain then swim again
	self.modelindex = modelindex_player; //go back to the player model

And that's it! the player can now swim!

Thank you MaNiAc for telling me how to adjust the player angles properly.

Tutorial html coding by Achilles.