#include extreme\_ex_weapons;

sprintInit()
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_dead");
	self endon("ex_spawned");

	// set the variables
	self.ex_sprinttime = level.ex_sprinttime;
	self.ex_playsprint = false;
	self.ex_sprintshow = false;
	self.ex_sprintstop = false;
	self.ex_pace = false;
	self.ex_moving = false;

	// draw the hud elements
	self thread sprinthud();

	// start the sprint movement monitor
	self thread sprintmovemon();

	// start the sprint function monitor
	self thread sprintmonitor();

	// start the sprint hud monitor
	if(level.ex_sprinthud) self thread sprinthudmon();

}

sprinthud()
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_dead");
	self endon("ex_spawned");

	if(level.ex_sprinthud)
	{
		self.ex_sprinthud_back = newClientHudElem(self);
		self.ex_sprinthud_back.alignX = "left";
		self.ex_sprinthud_back.alignY = "top";
		//self.ex_sprinthud_back.x = 528;
		self.ex_sprinthud_back.x = 545;
		self.ex_sprinthud_back.y = 417;
		self.ex_sprinthud_back.alpha = 1;
		self.ex_sprinthud_back setShader("gfx/hud/hud@health_back.tga", 12, 34);

		self.ex_sprinthud = newClientHudElem(self);
		self.ex_sprinthud.alignX = "left";
		self.ex_sprinthud.alignY = "top";
		//self.ex_sprinthud.x = 529;
		self.ex_sprinthud.x = 546;
		self.ex_sprinthud.y = 418;
		self.ex_sprinthud.alpha = 1;
		self.ex_sprinthud.color = ( 0, 0, 1);
		self.ex_sprinthud setShader("gfx/hud/hud@health_bar.tga", 10, 32);
	}

	if(level.ex_sprinthudhint)
	{
		self.ex_sprinthud_hint = newClientHudElem( self );
		self.ex_sprinthud_hint.alignX = "right";
		self.ex_sprinthud_hint.alignY = "top";
		self.ex_sprinthud_hint.fontScale = 0.7;
		self.ex_sprinthud_hint.x = 628;
		self.ex_sprinthud_hint.y = 398;
		self.ex_sprinthud_hint.alpha = 0;
		self.ex_sprinthud_hint setText(&"SPRINT_HINT");
	}
}

sprintmonitor()
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_dead");
	self endon("ex_spawned");

	// rese the recover time
	recovertime = 0;

	// set the default ammo
	sprintammo = 100;

	while (isAlive(self) && self.sessionstate == "playing")
	{
		wait 0.05;

		dupeslot = undefined;

		recover_check = self getWeaponSlotWeapon("primary");

		sprint = (level.ex_sprinttime - self.ex_sprinttime) / level.ex_sprinttime;

		// Disable sprinting if we carry a flag in heavy flag mode
		if (level.ex_sprintheavyflag && isdefined(self.flagAttached))
			self.ex_sprinttime = 0;

		if(self.ex_sprinttime < level.ex_sprinttime && recover_check != "sprint_mp")
		{
			// Don't increase sprinttime unless recovertime has passed
			if(recovertime >0 ) recovertime--;
			else self.ex_sprinttime++;
		}

		// keep the sprint bar updated
		self thread sprintbarupdate(sprint);

		if(!self.ex_moving) continue;

		// wait here until they press the use key, unless they are sprinting!
		if(!self.ex_sprinting && !self useButtonPressed()) continue;

		// ok, they've pressed the use key, but for how long?
		if(!self.ex_sprinting && self useButtonPressed())
		{
			// they're still pressing use, stop the weapon monitor ready for sprinting
			self.ex_stopwepmon = true;

			count = 0;

			while(self useButtonPressed() && count < 5)
			{
				wait 0.05;
				count++;

				current = self getCurrentWeapon();

				if(current != self.weapon["current"].name && (current == self.weapon["oldprimary"].name || current == self.weapon["oldprimaryb"].name))
					self.weapon["current"].name = current;
			}

			// appears to be a normal weapons change
			if(count < 5)
			{
				// start the weapons monitor, false alarm!
				self.ex_stopwepmon = false;
				continue;
			}
		}

		// ok, they pressed it for long enough, maybe they want to sprint?
		if(isPlayer(self) && self useButtonPressed() && self.ex_sprinttime > 0 && !self.ex_sprintstop)
		{
			// the weapons monitor has not stopped, no sprint boy!
			if(!self.ex_stopwepmon) continue;

			// if they are by an ammocrate possible going to rearm, no sprint
			if(isDefined(self.ex_amc_msg_displayed)) continue;

			// cannot sprint in SD if plant/defuse option is displayed
			if(level.ex_currentgt == "sd" && (isDefined(self.ex_planting) || isDefined(self.ex_defusing))) continue;
			
			// cannot sprint if not moving
			if(!self.ex_pace) continue;
			
			// cannot sprint if stance does not match
			if(self.ex_stance > (level.ex_sprint - 1))
			{
				if(self.ex_sprinting) self.ex_sprintstop = true;
				continue;
			}

			// cannot sprint if your carrying a mobile mg
			if((self.weapon["current"].name == "mobile_30cal" || self.weapon["current"].name == "mobile_mg42") && level.ex_sprintheavymg)
			{
				self thread sprintMessage(&"SPRINT_NOMGSPRINT", 3);
				continue;
			}

			// cannot sprint while healing
			if(isDefined(self.ex_ishealing)) continue;

			// cannot sprint while using binoculars
			if(self.ex_binocuse) continue;

			count = 0;

			primary = self getWeaponSlotWeapon("primary");
			primaryb = self getWeaponSlotWeapon("primaryb");

			if(primary == self.weapon["oldprimary"].name && primaryb == self.weapon["oldprimaryb"].name)
			{
				self notify("weaponsave"); // everything's cool, save the weapons we have now..
				self waittill("weaponsaved");
			}

			// have they picked up a weapon by mistake?
			if(!self.ex_sprinting && primary != "sprint_mp")
			{
				// check the primary and primaryb, have they picked up a weapon?
				if(primary != self.weapon["oldprimary"].name || primaryb != self.weapon["oldprimaryb"].name)
				{
					// which slot is this new weapon in?
					if(primary != self.weapon["oldprimary"].name) // yes it's in the primary slot!
					{
						if(!isDummy(primary)) dupeslot = "primary";
					}
					else if(primaryb != self.weapon["oldprimaryb"].name) // yes it's in the primaryb slot!
					{
						if(!isDummy(primaryb)) dupeslot = "primaryb";
					}
					else dupeslot = undefined; // no, they haven't so lets sprint!

					if(isDefined(dupeslot)) // if they have picked up a weapon, lets give them back the right one and get rid of the duplicates
					{
						if(isValidWeapon(self.weapon[dupeslot].name))
						{
							// this is the wrong weapon drop it!
							self dropcurrentweapon();
						
							// give them back the right weapon for that slot
							self setWeaponSlotWeapon(dupeslot, self.weapon[dupeslot].name);
							self setWeaponSlotClipAmmo(dupeslot, self.weapon[dupeslot].clip);
							self setWeaponSlotAmmo(dupeslot, self.weapon[dupeslot].reserve);
							
							// ok, we also have the original weapon swapped, can't let them get more ammo from it so, lets remove it from the map
							self thread extreme\_ex_utils::deletePlacedEntity("weapon_" + self.weapon[dupeslot].name);
						}
					}
				}

				self notify("weaponsave"); // everything's cool, save the weapons we have now..
				self waittill("weaponsaved");

				// ok, time to run....lets get the sprint weapon in the primary slot
				self setWeaponSlotWeapon("primary", "sprint_mp");
				self switchToWeapon("sprint_mp");
				self setWeaponSlotAmmo("primary",0);
				self.ex_playsprint = true;
				self thread sprintsound();
				self.ex_stopwepmon = true;
				self.ex_sprinting = true;
			}
			else
			{
				// decrease the available sprint time depending on stance
				rate = 3; // prone
				if(self.ex_stance == 0) rate = 1; // standing
				else if(self.ex_stance == 1) rate = 2; // crouching
	
				self.ex_sprinttime-= rate;
				self.ex_sprinting = true;
	
				// update the sprint ammo counter
				sprintammo = int(100 * (1.0 - sprint));
				self setWeaponSlotAmmo("primary", sprintammo);
			}
		}
		else
		{
			self.ex_playsprint = false;
			self.ex_sprinting = false;
			self.ex_sprintstop = false;

			// did they stop sprinting?
			if(self getWeaponSlotWeapon("primary") == "sprint_mp")
			{
				// restore the primary they had when sprint began
				if(isValidWeapon(self.weapon["oldprimary"].name))
				{
					self setWeaponSlotWeapon("primary", self.weapon["oldprimary"].name);
					self setWeaponSlotClipAmmo("primary", self.weapon["oldprimary"].clip);
					self setWeaponSlotAmmo("primary", self.weapon["oldprimary"].reserve);
				}

				// restore the secondary they had when sprint began
				if(isValidWeapon(self.weapon["oldprimary"].name))
				{
					self setWeaponSlotWeapon("primaryb", self.weapon["oldprimaryb"].name);
					self setWeaponSlotClipAmmo("primaryb", self.weapon["oldprimaryb"].clip);
					self setWeaponSlotAmmo("primaryb", self.weapon["oldprimaryb"].reserve);
				}

				// restore old current weapon that we have saved
				if(isValidWeapon(self.weapon["current"].name)) self switchToWeapon(self.weapon["current"].name);
				
				// reset the recover time variable
				recovertime = level.ex_sprintrecovertime;

				// calculate the recover time of full sprint time has not been used
				if(self.ex_sprinttime > 0) recovertime = int(recovertime * sprint + 0.5);

				// start the weapons monitor again
				self.ex_stopwepmon = false;
			}
		}
	}

	// clear the crap of their screen!, nice aren't we?
	if(isDefined(self.ex_sprinthud)) self.ex_sprinthud destroy();
	if(isDefined(self.ex_sprinthud_back)) self.ex_sprinthud_back destroy();
	if(isDefined(self.ex_sprinthud_hint)) self.ex_sprinthud_hint destroy();
}

sprintMessage(msg, time)
{
  if(!isDefined(self.ex_sprintmsg))
  {
    self.ex_sprintmsg = true;
    self iprintlnbold(msg);
    wait(time);
    [[level.ex_clearlnb]]("self", 5);
    self.ex_sprintmsg = undefined;
  }
}

sprintmovemon()
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_dead");
	self endon("ex_spawned");

	while(isPlayer(self) && isAlive(self) && self.sessionstate=="playing")
	{
		// Get the stance
		self.ex_stance = [[level.ex_getStance]](false);

		if(isPlayer(self))
		{
			// Calculate current speed
			oldpos = self.origin;
			wait 0.5;

			if(isPlayer(self))
			{
				speed = distance(oldpos, self.origin);

				// disable firstaid
				if(speed > 1) self.ex_moving = true;
				else self.ex_moving = false;

				// show sprint message
				if(speed > 10) self.ex_pace = true;
				else self.ex_pace = false;
			}
		}
	}
}

sprinthudmon()
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_dead");
	self endon("ex_spawned");

	while(isPlayer(self) && isAlive(self) && self.sessionstate=="playing")
	{
		wait 0.5;
		
		// show or hide the sprint hint
		if(isPlayer(self) && level.ex_sprint && level.ex_sprinthudhint)
		{
			if(!self.ex_sprintshow && self.ex_sprinttime && !self.ex_sprinting && self.ex_pace && (level.ex_sprint - 1) >= self.ex_stance)
			{
				if(isDefined(self.ex_sprinthud_hint))
				{
					self.ex_sprinthud_hint fadeOverTime (2); 
					self.ex_sprinthud_hint.alpha = 0.8;
				}

				self.ex_sprintshow = true;

			}
			else if(isPlayer(self) && self.ex_sprintshow && (self.ex_sprinting || !self.ex_pace || (level.ex_sprint - 1) < self.ex_stance))
			{
				{
					if(isDefined(self.ex_sprinthud_hint))
					{
						self.ex_sprinthud_hint fadeOverTime (2); 
						self.ex_sprinthud_hint.alpha = 0;
					}
						
					self.ex_sprintshow = false;
				}
			}
		}
	}
}

sprintsound()
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_dead");
	self endon("ex_spawned");

	if(!self.ex_playsprint) return;

	self.ex_headmarker stoploopsound();

	stage = int(level.ex_sprinttime / 3);
	spshort = false;
	spmedium = false;
	splong = false;
	crpr = false;

	wait 2;

	self.ex_headmarker playloopsound("sprint");

	while(isPlayer(self) && self.ex_playsprint)
	{
		 wait 0.1;

		if(self.ex_stance == 0) 
		{
			crpr = false;
			
			if(self.ex_sprinttime > stage * 2 && !spshort) spshort = true;
			else if(self.ex_sprinttime < stage * 2) spshort = false;

			if(self.ex_sprinttime > stage && self.ex_sprinttime < stage * 2 && !spshort && !spmedium) spmedium = true;
			else if(self.ex_sprinttime  < stage || self.ex_sprinttime > stage * 2) spmedium = false;

			if(self.ex_sprinttime < stage && !spshort && !spmedium && !splong) splong = true;
			else if(self.ex_sprinttime > stage) splong = false;
		}
		else if(crpr)
		{
			self.ex_headmarker stoploopsound();
			self.ex_headmarker playsound("sprintover");
			crpr = true;
		}
	}

	if(isPlayer(self)) self.ex_sprintreco = true;

	if(spshort) wait 2;
	else if(spmedium) wait 3;
	else wait 4;

	if(isPlayer(self))
	{
		self.ex_headmarker stoploopsound();
		self.ex_sprintreco = false;
		self.ex_headmarker playsound("sprintover");
	}
}

sprintbarupdate(sprint)
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_dead");
	self endon("ex_spawned");

	if(isPlayer(self))
	{
		if(isDefined(self.ex_sprinthud))
		{
			if(!self.ex_sprinttime) self.ex_sprinthud.color = ( 1.0, 0.0, 0.0);
			else self.ex_sprinthud.color = (sprint, 0, 1.0-sprint);
		}
		
		self.ex_hudheight = 32 - int(32 * (1.0 - sprint));
			
		if(self.ex_hudheight < 1) self.ex_hudheight = 1;

		if(isDefined(self.ex_sprinthud))
		{
			if(self.ex_sprinttime == level.ex_sprinttime) self.ex_sprinthud.alpha = 0;
			else self.ex_sprinthud.alpha = 1;
		}

		if(isDefined(self.ex_sprinthud))
		{	
			if(level.ex_sprinthud) self.ex_sprinthud setShader("gfx/hud/hud@health_back.tga", 10, self.ex_hudheight);
			else self.ex_sprinthud setShader("gfx/hud/hud@health_bar.tga", 10, self.ex_hudheight);
		}
	}
}
