// SauerMod - MODENGINE - Engine Extensions by Quinton Reeves
// This extends igame.h igameclient

virtual void recomputecamera()
{
	extern bool deathcam;
	extern physent *player, *camera1;
	
	if(deathcam && player->state!=CS_DEAD) deathcam = false;
	extern int testanims;
	if(((editmode && !testanims) || !thirdperson) && player->state!=CS_DEAD)
	{
		//if(camera1->state==CS_DEAD) camera1->o.z -= camera1->eyeheight-0.8f;
		camera1 = player;
	}
	else
	{
		static physent tempcamera;
		camera1 = &tempcamera;
		if(deathcam) camera1->o = player->o;
		else
		{
			*camera1 = *player;
			if(player->state==CS_DEAD) deathcam = true;
		}
		camera1->reset();
		camera1->type = ENT_CAMERA;
		camera1->move = -1;
		camera1->eyeheight = 2;
		
		loopi(10)
		{
			if(!moveplayer(camera1, 10, true, thirdpersondistance)) break;
		}
	}
}
virtual void findorientation()
{
	extern physent *camera1;
	vec dir;
	vecfromyawpitch(camera1->yaw, camera1->pitch, 1, 0, dir);
	vecfromyawpitch(camera1->yaw, 0, 0, -1, camright);
	vecfromyawpitch(camera1->yaw, camera1->pitch+90, 1, 0, camup);

	if(raycubepos(camera1->o, dir, worldpos, 0, RAY_CLIPMAT|RAY_SKIPFIRST) == -1)
		worldpos = dir.mul(10).add(camera1->o); //otherwise 3dgui won't work when outside of map
}

virtual void fixcamerarange()
{
	extern physent *camera1;
	const float MAXPITCH = 90.0f;
	if(camera1->pitch>MAXPITCH) camera1->pitch = MAXPITCH;
	if(camera1->pitch<-MAXPITCH) camera1->pitch = -MAXPITCH;
	while(camera1->yaw<0.0f) camera1->yaw += 360.0f;
	while(camera1->yaw>=360.0f) camera1->yaw -= 360.0f;
}

virtual void mousemove(int dx, int dy)
{
	extern int sensitivity, sensitivityscale, invmouse;
	extern physent *player, *camera1;
	const float SENSF = 33.0f;	 // try match quake sens
	camera1->yaw += (dx/SENSF)*(sensitivity/(float)sensitivityscale);
	camera1->pitch -= (dy/SENSF)*(sensitivity/(float)sensitivityscale)*(invmouse ? -1 : 1);
	extern void fixcamerarange();
	fixcamerarange();
	if(camera1!=player && player->state!=CS_DEAD)
	{
		player->yaw = camera1->yaw;
		player->pitch = camera1->pitch;
	}
}
virtual bool wantcrosshair()
{
	extern physent *player;
	extern int hidehud;
	extern bool menuactive();
	return !(hidehud || player->state==CS_SPECTATOR) || menuactive();
};
virtual bool gamethirdperson() { extern int thirdperson; return thirdperson; } ;
virtual char *gamepakdir() { return "base"; };
virtual char *gametitle() { return gameident(); };

virtual bool gethudcolour(vec &colour, int fogmat)
{
	extern int curtime, dblend, damageblendfactor;

	if (dblend)
	{
		colour = vec(1.0f, 0.1f, 0.1f);
		
		dblend -= curtime*100/damageblendfactor;
		if(dblend<0) dblend = 0;
		
		return true;
	}
	else if (fogmat==MT_WATER || fogmat==MT_LAVA)
	{
		uchar col[3];
		if(fogmat==MT_WATER) getwatercolour(col);
		else getlavacolour(col);

		float maxc = max(col[0], max(col[1], col[2]));
		float blend[3];

		loopi(3) blend[i] = col[i] / min(32 + maxc*7/8, 255);

		colour = vec(blend[0], blend[1], blend[2]);

		return true;
	}
	return false;
}

virtual void loadworld(const char *name) { return; };
virtual void saveworld(const char *name) { return; };

virtual float stairheight(physent *d) { return 4.1f; }
virtual float floorz(physent *d) { return 0.867f; }
virtual float slopez(physent *d) { return 0.5f; }
virtual float wallz(physent *d) { return 0.2f; }
virtual float jumpvel(physent *d) { return 125.0f; }
virtual float gravity(physent *d) { return 200.0f; }
virtual float stepspeed(physent *d) { return 1.0f; }
virtual float watergravscale(physent *d) { return 4.0f; }
virtual float waterdampen(physent *d) { return 8.f; }
virtual float waterfric(physent *d) { return 20.f; }
virtual float floorfric(physent *d) { return 6.f; }
virtual float airfric(physent *d) { return 30.f; }

virtual vec feetpos(physent *d)
{
	//if (d->type == ENT_PLAYER || d->type == ENT_AI)
	//	return vec(d->o).sub(vec(0, 0, d->eyeheight));
	return vec(d->o);
}

virtual void updateroll(physent *d)
{
	extern int maxroll, curtime;
	
	if(d->strafe==0)
	{
		d->roll = d->roll/(1+(float)sqrtf((float)curtime)/25);
	}
	else
	{
		d->roll += d->strafe*curtime/-30.0f;
		if(d->roll>maxroll) d->roll = (float)maxroll;
		if(d->roll<-maxroll) d->roll = (float)-maxroll;
	}
}

virtual void menuevent(int event)
{
	const char *s = NULL;
	
	switch (event)
	{
		case MN_BACK: s = "sfx/back"; break;
		case MN_INPUT: s = "sfx/input"; break;
		default: break;
	}

	if (s) playsoundname((char *)s);
}
