
doPlayerBleed(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime)
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon ("StopBleeding");
	self endon("ex_spawned");
	self endon("ex_dead");

	wait 1;

	bleedV = [];
	bleedV = getBleedData(sMeansOfDeath, sWeapon, sHitLoc);

	if(!isDefined(bleedV["bleedmsg"])) return;

	if(isPlayer(self))
	{
		if(isalive(self) && (self.health < level.ex_startbleed) && !self.ex_bleeding)
		{
			self.ex_bleeding = true;
			bleedcount = level.ex_maxbleed;

			msg = bleedV["bleedmsg"];

			switch(level.ex_bleedmsg)
			{
				case 0: self iprintln(msg); break;
				case 1: self iprintlnbold(msg); break;
				case 2: self thread playerBleedMsg(msg); break;
				default: self thread extreme\_ex_utils::ex_hud_announce(msg, 0); break;
			}

			while ((bleedcount > 0) && isalive(self) && (self.health < level.ex_startbleed))
			{
				if(self.health > 1)
				{
					self.health--;
					if(!self.ex_bphockinit) self thread doBleedPainShock();
					if(!self.ex_bsoundinit) self thread doBleedPainSound();
					playfxontag(level.ex_effect["bleeding"], self, bleedV["bleedpos"]);
				}
				else self finishPlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime);

				bleedcount--;
				wait bleedV["bleeddly"];
			}

			self.ex_bleeding = false;
			self.ex_bsoundinit = false;
			self.ex_bphockinit = false;

			if(level.ex_bleedmsg && isalive(self) && (self.health > level.ex_startbleed))
			{
				msg = &"BLEED_STOPPED";

				switch(level.ex_bleedmsg)
				{
					case 0: self iprintln(msg); break;
					case 1: self iprintlnbold(msg); break;
					case 2: self thread playerBleedMsg(msg); break;
					default: self thread extreme\_ex_utils::ex_hud_announce(msg, 0); break;
				}
			}
			else if(!level.ex_bleedmsg && isalive(self) && (self.health > level.ex_startbleed)) self iprintln(&"BLEED_STOPPED");
		}
	}
}

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

	if(!level.ex_bleedsound) return;

	self.ex_bsoundinit = true;
	sounddelay = 5.0;

	while(isPlayer(self) && self.sessionstate == "playing" && isdefined(self.ex_bleeding) && (self.health < level.ex_startbleed))
	{
		if(self.health >= 1 && self.health <= 5) sounddelay = 1.0;
		else if(self.health >= 6 && self.health <= 10) sounddelay = 1.5;
		else if(self.health >= 11 && self.health <= 25) sounddelay = 2.0;
		else if(self.health >= 26 && self.health <= 50) sounddelay = 3.0;
		else if(self.health >= 51 && self.health <= 75) sounddelay = 4.0;
		else sounddelay = 5.0;

		switch(level.ex_bleedsound)
		{
			case 1:  // Play sound so ALL players can hear ( mode 1 )
			self playSound("generic_pain");
			break;

			default: // Play sound so ONLY the bleeding player can hear ( mode 2 )
			self playLocalSound("breathing_hurt");
			break;
		}

		wait sounddelay;
	}
}

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

	self.ex_bphockinit = true;
	shocktime = 1;

	while (isalive(self) && isdefined(self.ex_bleeding) && (self.health < level.ex_startbleed))
	{
		if(self.health >= 1 && self.health <= 5) shocktime = 10;
		else if(self.health >= 6 && self.health <= 10) shocktime = 5;
		else if(self.health >= 11 && self.health <= 25) shocktime = 4;
		else if(self.health >= 26 && self.health <= 50) shocktime = 3;
		else if(self.health >= 51 && self.health <= 75) shocktime = 2;

		self shellshock("medical", shocktime);

		wait shocktime + (randomInt(10) + 5);
	}
}

playerBleedMsg(bleedmsg)
{
	level endon("ex_gameover");
	self endon("disconnect");
	self endon("ex_spawned");
	self endon("ex_dead");
		
	if(!isdefined(self.ex_bleedmsg))
	{
		self.ex_bleedmsg = newClientHudElem(self);
		self.ex_bleedmsg.x = 320;
		self.ex_bleedmsg.y = 420;
		self.ex_bleedmsg.alignX = "center";
		self.ex_bleedmsg.alignY = "middle";
		self.ex_bleedmsg.alpha = 1.0;
		self.ex_bleedmsg.fontScale = 1.0;
	}

	wait 0.5;

	if(isdefined(self.ex_bleedmsg))
	{
		self.ex_bleedmsg setText(bleedmsg);
		self.ex_bleedmsg fadeOverTime(2);
		self.ex_bleedmsg.alpha = 1;
	}

	wait 5;

	if(isdefined(self.ex_bleedmsg))
	{	
		self.ex_bleedmsg fadeOverTime(2);
		self.ex_bleedmsg.alpha = 0;
	}
}

getBleedData(sMeansOfDeath, sWeapon, sHitLoc)
{
	pmsg = undefined;
	tagloc = undefined;
	delay = undefined;

	switch(sHitLoc)
	{
		case "neck":				pmsg = &"BLEED_NECK"; tagloc = "j_neck"; delay = 0.7; break;
		case "head":				pmsg = &"BLEED_HEAD"; tagloc = "j_head"; delay = 0.4; break;
		case "helmet":				pmsg = &"BLEED_HELMET"; tagloc = "j_head"; delay = 0.9; break;
		case "torso_upper":			pmsg = &"BLEED_UPPERBODY"; tagloc = "j_neck"; delay = 1.0; break;
		case "torso_lower":			pmsg = &"BLEED_LOWERBODY"; tagloc = "pelvis"; delay = 1.0; break;
		case "left_leg_upper":			pmsg = &"BLEED_UPPERLEFTLEG"; tagloc = "j_knee_le"; delay = 1.2; break;
		case "right_leg_upper":			pmsg = &"BLEED_UPPERRIGHTLEG"; tagloc = "j_knee_ri"; delay = 1.2; break;
		case "left_leg_lower":			pmsg = &"BLEED_LOWERLEFTLEG"; tagloc = "j_knee_le"; delay = 1.5; break;
		case "right_leg_lower":			pmsg = &"BLEED_LOWERRIGHTLEG"; tagloc = "j_knee_ri"; delay = 1.5; break;
		case "left_foot":				pmsg = &"BLEED_LEFTFOOT"; tagloc = "j_ankle_le"; delay = 2.5; break;
		case "right_foot":			pmsg = &"BLEED_RIGHTFOOT"; tagloc = "j_ankle_ri"; delay = 2.5; break;
		case "left_arm_upper":			pmsg = &"BLEED_UPPERLEFTARM"; tagloc = "j_shoulder_le"; delay = 1.5; break;
		case "right_arm_upper":			pmsg = &"BLEED_UPPERRIGHTARM"; tagloc = "j_shoulder_ri"; delay = 1.5; break;
		case "left_arm_lower":			pmsg = &"BLEED_LOWERLEFTARM"; tagloc = "j_wrist_le"; delay = 1.5; break;
		case "right_arm_lower":			pmsg = &"BLEED_LOWERRIGHTARM"; tagloc = "j_wrist_ri"; delay = 1.5; break;
		case "left_hand":				pmsg = &"BLEED_LEFTHAND"; tagloc = "j_wrist_le"; delay = 2.0; break;
		case "right_hand":			pmsg = &"BLEED_RIGHTHAND"; tagloc = "j_wrist_ri"; delay = 2.0; break;

		case "none":
		{
			switch(sMeansOfDeath)
			{
				case "MOD_EXPLOSIVE":
				{
					switch(sWeapon)
					{
						case "artillery_mp": pmsg = &"BLEED_ARTILLERY"; break;
						case "plane_mp": pmsg = &"BLEED_PLANECRASH"; break;
						case "tripwire_mp": pmsg = &"BLEED_TRIPWIRE"; break;
						case "planebomb_mp": pmsg = &"BLEED_PLANEBOMB"; break;
					}
				}
				break;
				
				case "MOD_GRENADE":
				{
					switch(sWeapon)
					{
						case "mortar_mp": pmsg = &"BLEED_MORTAR"; break;
						case "planebomb_mp": pmsg = &"BLEED_PLANEBOMB"; break;
					}
				}
				break;

				case "MOD_GRENADE_SPLASH": pmsg = &"BLEED_GRENADE_SPLASH"; break;
				case "MOD_FALLING": pmsg = &"BLEED_FALLING"; break;
			}
		}
					
		tagloc = "pelvis";
		delay = 2.0;
		break;

		default: pmsg = &"BLEED_GENERIC"; tagloc = "pelvis"; delay = 2.0; break;
	}

	bleedV["bleedmsg"] = pmsg;
	bleedV["bleedpos"] = tagloc;
	bleedV["bleeddly"] = delay;
	
	return bleedV;
}
